Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a 'default' trait in FactoryGirl to avoid unnecessary association creation

Is it possible to define a default trait in FactoryGirl? If I define a factory like this (where both question_response belongs_to question):

factory :question_response do
  question
  work_history

  trait :open do
    question { FactoryGirl.create :question, question_type: 'open' }
  end
end

When I do FactoryGirl.create :question_response, :open it will first create a default question and then create another inside the trait, which is an unnecessary operation.

Ideally I'd like to do this:

factory :question_response do
  work_history

  trait :default do
    question { FactoryGirl.create :question, question_type: 'yes_no' }
  end

  trait :open do
    question { FactoryGirl.create :question, question_type: 'open' }
  end
end

And then doing FactoryGirl.create :question will use the default trait, but it doesn't seem to be possible.

like image 693
Sam Stickland Avatar asked Jun 14 '15 13:06

Sam Stickland


People also ask

What is FactoryBot used for?

Factory Bot (previously known as Factory Girl) is a library gem specific to Ruby. It creates test fixtures, these test fixtures can be used as a tool to help with automated testing. Factory Bot is intended to be more dynamic than the default fixtures that Rails has.

What is FactoryBot in Rspec?

To do this we will use the Factory Bot gem which allows the developer to set default values for the instances of our class that we create. The methods Factory Bot provides are create, build, attributes_for, and build_stubbed. The two most important are the create and build.

What is Build_stubbed?

build_stubbed imitates creating. It slubs id , created_at , updated_at and user_id attributes. Also it skips all validations and callbacks. Stubs means that FactoryBot just initialize object and assigns values to the id created_at and updated_at attributes so that it just looks like created.


2 Answers

When I do FactoryGirl.create :question_response, :open it will first create a default question and then create another inside the trait

It's not true. if you specify the trait with question, it will overwrite the factory behavior before creation so that it does not create a default question.

I checked it with FactoryGirl v4.5.0

like image 107
kuboon Avatar answered Oct 02 '22 19:10

kuboon


Just in case someone else is looking for 'default trait' scenario, this was discussed with examples in https://github.com/thoughtbot/factory_bot/issues/528#issuecomment-18289143

Basically, you can define trait with defaults and then use it for different factories. And then you can use appropriate factory with needed configuration.

For example:

FactoryBot.define do
  trait :user_defaults do
    email { Faker::Internet.unique.email }
    username { Faker::Internet.unique.username }
    password { "test1234" }
  end

  factory :with_admin_role, class: User do
    user_defaults

    after(:create) do |user, _|
      user.add_role :admin
    end
  end

  factory :with_readonly_role, class: User do
    user_defaults

    after(:create) do |user, _|
      user.add_role :readonly
    end
  end
end
like image 43
Alex P Avatar answered Oct 02 '22 20:10

Alex P