Skip to content
gabebw edited this page Apr 8, 2012 · 14 revisions

Defining Factories

You can add factories to any of the following places:

  1. test/factories.rb (Test::Unit)
  2. spec/factories.rb (RSpec)
  3. test/factories/*.rb
  4. spec/factories/*.rb

A typical factory file looks like this:

FactoryGirl.define do
  factory :user do
    first_name 'John'
    last_name  'Doe'
    age        { 1 + rand(100) }
    
    # Child of :user factory, since it's in the `factory :user` block
    factory :admin do
      admin true
    end
  end
end

Make sure to add this to your RSpec configure block:

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

Make sure to add this for Test::Unit:

class ActiveSupport::TestCase
  include FactoryGirl::Syntax::Methods
end

Make sure to add this for Cucumber (an appropriate place is in the env.rb file):

World FactoryGirl::Syntax::Methods

Using factories

Once your factories are defined, you can use them in the following ways:

# Saved instance
user = create(:user)

# Unsaved instance
user = build(:user)

# Attribute hash (ignores associations)
user_attributes = attributes_for(:user)

# Stubbed object
user_stub = build_stubbed(:user)

# Override attributes
user = create(:user, first_name: 'Joe')

Sequences and associations

If you need uniqueness on a field, sequencing comes in handy. The sequences can then be used in your other definitions

FactoryGirl.define do
  sequence :email do |n|
    "email#{n}@factory.com"
  end

  factory :user do
    email
    password "foobar"
    password_confirmation "foobar"
  end
end

Or you can generate an email anywhere in your code:

new_email = FactoryGirl.generate(:email)

Sequencing can also be defined within the factory definition. This lets you define a sequence that is only incremented when a new user is built or created. Otherwise, FactoryGirl.generate(:email) would increment the sequence.

FactoryGirl.define do
  factory :user do
    sequence(:email) {|n| "email#{n}@factory.com" }
    password "foobar"
    password_confirmation "foobar"
  end
end

For completeness’ sake, we can make password_confirmation match the password by using a block to define its value.

FactoryGirl.define do
  factory :user do
    sequence(:email) {|n| "email#{n}@factory.com" }
    password "foobar"
    password_confirmation { |u| u.password }
  end
end

The sequencing also works for associations. The code below will create a new user with the sequenced email from above.

FactoryGirl.define do
  factory :post do
    name "Post name"
    user
  end
end