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