factory_bot
factory_bot copied to clipboard
Allow factories to use RSpec example methods such as `double`
This can either be an improvement or something to add to the documentation as suggested by Daniel J Colson on Twitter.
The simple feature is to, at least, use RSpec's double
within a factory's initialize_with
.
How
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.before(:suite) do
FactoryBot.find_definitions
FactoryBot::Evaluator.include RSpec::Mocks::ExampleMethods
end
end
Why?
I've written a test suite for a third party API and I need to mock the response. For external requests I'm using Webmock with VCR but that has no bearing on this particular issue. The issue is to test my own code before any external API ever needs to be hit. Here's a sample:
FactoryBot.define do
Response = Trav3::Response
factory :response do
initialize_with do
dbl = double
allow(dbl).to receive(:body).and_return( { a: :b, c: :d }.to_json )
new(build(:travis), dbl)
end
end
end
Now I can use the nice and readable format of double
within initialize_with
and don't have to resort to:
dbl = Object.new
dbl.define_singleton_method(:body) { { a: :b, c: :d }.to_json }
I came across https://github.com/thoughtbot/factory_bot/issues/703, which seems somewhat related.
Thanks @composerinteralia . I find it interesting that @printercu used the class FactoryGirl::SyntaxRunner
to include on. I'm not sure if one is better than the other.
The way I went about solving where, and what, to include the desired methods was first in a rspec test I used byebug
to find method(:double).owner
to get RSpec::Mocks::ExampleMethods
and then again within initialize_with
within a factory I used byebug
to get the class name for which to include the module in FactoryBot::Evaluator
. And afterwards it just worked.
It is nice to know that there was an answer out there to find already. But when I searched online I did not come across any answers. It's likely I didn't have the right search words/terms to get to it. That's one reason why I think this would really be helpful to have in the official docs.
I haven't had time to work on this yet, but I also spotted another issue that might be related: https://github.com/thoughtbot/factory_bot/issues/564.
Wondering if this will work for you:
FactoryBot.define do
Response = Trav3::Response
factory :response do
body { { a: :b, c: :d }.to_json }
end
end