Search code examples
ruby-on-railsrspecfactory-bot

Circular dependency in FactoryBotRails Factories


spec/factories/company.rb

FactoryBot.define do
  factory :company do
    name { Faker::Name.unique.name }
    time_zone_name { Faker::Address.time_zone }
    users { [ FactoryBot.create(:user) ]  }  
  end
end

spec/factories/company.rb

FactoryBot.define do
  factory :user do
    email { Faker::Internet.email }
    password {'123qwe123'}
    name { Faker::Superhero::name }
    association :company, factory: :company
  end
end

app/model/company.rb

class Company < ApplicationRecord


  validate :check_users_present?
  has_many :users

  private    
  def check_users_present?
    errors.add(:base, "You must provide at least one user") if users.size < 1
  end

end

app/model/user.rb

class User < ApplicationRecord
  belongs_to :company
end

when I am trying to make a :company it throws SystemStackError (stack level too deep).

since we have validation for creating at least one user with the company and user requires company. we are having a circular dependency issue.

i tried this solution, but that doesnt seems to fix it. or i am not sure how to do it properly (How to avoid circular creation of associated models in factory_girl? )

i tried using transient but i am not sure how to configure it for has_many associations. please can someone help me in figuring this out


Solution

  • Here's the circular dependency:

    FactoryBot.define do
      factory :company do
        ...
        users { [ FactoryBot.create(:user) ]  } # HERE
      end
    end
    
    FactoryBot.define do
      factory :user do
        ...
        association :company, factory: :company # AND HERE
      end
    end
    

    When trying to create a company with FactoryGirl, it invokes FactoryBot.create to create a new user, which at the same time is verifying the company factory.

    If you want to add associations, I'd personally advice you to do it in your examples, not in the factories. Since the factories are meant to be used along your whole projects, and there are tests that aren't going to share the same logic as you´re testing today, as a matter of fact, that might change sooner or later.