Factory Bot: Association creates circular logic

59 Views Asked by At

I have 2 factories that reference each other and create circular logic that results in error.

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }

    trait :with_client do
      client
    end
  end
end

FactoryBot.define do
  factory :client do
    name { Faker::Name.name }
    phone { Faker::Number.number(digits: 10) }

    user
  end
end

When I call create(:user, :with_client) it creates a new Client but then that factory attempts to create a new User rather than using the existing one. Is there a way to tell it to use the User that was already created?

1

There are 1 best solutions below

0
nitsas On

If you don't care about the user's details, just create a client and get the user through that:

let(:client) { FactoryBot.create(:client) }
let(:user) { client.user }

Otherwise, you can define a trait in client's factory that avoids creating a user, and use that in user's factory:

FactoryBot.define do
  factory :client do
    name { Faker::Name.name }
    phone { Faker::Number.number(digits: 10) }

    user

    trait :without_user do
      user { nil }
    end
  end
end

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }

    trait :with_client do
      association :client, :without_user
    end
  end
end

# This way you can create users with clients and override the user's details:
let(:user) { FactoryBot.create(:user, :with_client, name: 'John Doe') }