Skip to content

Add example for belongs_to/has_many factory

What does this MR do and why?

This MR adds an example for creating a factory for a belongs_to/has_many relationship because it's not obvious how to implement this in a way that doesn't cause a rubocop failure.

For example, I first tried the following:

FactoryBot.define do
  factory :car do
    after(:create) do |car, evaluator|
      create_list(:wheel, 2, car: car)
    end
  end
end

FactoryBot.define do
  factory :wheel do
    car { association :car }
  end
end

but this caused a rubocop error:

Prefer inline `association` over `create_list`. 
See https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#factories [RSpec/FactoryBot/StrategyInCallback]

If you visit the above link, it explains:

Prefer implicit, explicit, or inline associations over create / build for association setup in callbacks. See issue #262624 for further context.

If you visit the implicit/explicit/inline links, it's not immediately obvious how to set up a factory for a belongs_to/has_many relationship.

If you look through other factories in ee/spec/factories/ for inspiration, you'll notice that most of them are using the disallowed pattern after(:create) { |obj| create_list(:factory, relation: obj) }, however, these definitions are able to avoid the rubocop errors because they’ve all been added as exceptions in .rubocop_todo/rspec/factory_bot/strategy_in_callback.yml.

The actual solution for this problem is to use the instance method which is explained in the factorybot docs for has_and_belongs_to_many associations, but this is not at all obvious.

Because of the difficulty I had figuring this out, I thought it would be a useful addition to the documentation.

Screenshots or screen recordings

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Adam Cohen

Merge request reports

Loading