Sonntag, 9. August 2015

Set associations in FactoryGirl!

Fixtures are not suitable for testing. They are difficult to maintain and require explicit instantiation of test objects. This is particularly true for associations.
Instead, factories should be be used to generate test objects. The widespread gem Factory Girl lends itself to it. For example, the models/person_spec.rb:
require 'active_record_spec_helper'
require 'person.rb'
require 'address.rb

describe Person do
  subject { FactoryGirl.build :person }

  describe "validations" do
    FactoryGirl.create :address
    if { is_expected.to validate_presence_of(:address) }
  end
end
A person shall only be valid if it also has a valid address. The factories/address.rb:
FactoryGirl.define do
  factory :address do
    street 'Main street'
    number 1
    zip 12345
  end
end
The factories/person.rb:
FactoryGirl.define do
  factory :person do
    name 'Christian'
    surname 'Rolle'
    address_id 1
  end
end
The people factory has defined an address_id association by setting a plain ID. That is very fragile. Especially since a valid person is expected to own a valid address object.
The association could be mocked or the FactoryGirl association feature could be used for some reasons (factories/person.rb):
FactoryGirl.define do
  factory :person do
    name 'Christian'
    surname 'Rolle'
    association :address, strategy: :build
  end
end
The address association will not be actively saved. That saves touching the database in each test and therefore speed up the test tremendously (models/person_spec.rb):
require 'active_record_spec_helper'
require 'person.rb'
require 'address.rb

describe Person do
  subject { FactoryGirl.build :person }

  describe "validations" do
    if { is_expected.to validate_presence_of(:address) }
  end
end
In most tests the associations presence is sufficient. If indeed a stored association is required (eg named scopes), that explicit saving approach is way more expressive.
Further articles of interest:

Supported by Ruby 2.2.1, Ruby on Rails 4.2.1, RSpec 3.3.2 and FactoryGirl 4.5.0