factory_bot icon indicating copy to clipboard operation
factory_bot copied to clipboard

Allow factories to use RSpec example methods such as `double`

Open danielpclark opened this issue 5 years ago • 4 comments

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 }

danielpclark avatar Jan 24 '19 20:01 danielpclark

I came across https://github.com/thoughtbot/factory_bot/issues/703, which seems somewhat related.

composerinteralia avatar Feb 06 '19 14:02 composerinteralia

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.

danielpclark avatar Feb 06 '19 14:02 danielpclark

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.

composerinteralia avatar Mar 31 '19 19:03 composerinteralia

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

pirj avatar Nov 20 '20 09:11 pirj