Factories with ancestry for Testing

1.3k Views Asked by At

I want to run some RSpec tests to test Ancestry in Rails. I want to use FactoryGirl to create the Institution instances for the tests. I have tried the following ways mentioned below, but have not been successful in creating the child records.

factories.rb file

  factory :institution do
    # sequence(:name) { |n| "University of XYZ#{n}" }
  end

And in the tests I am using the following styles Style: 1

let(:institution){ FactoryGirl.create(:institution, name: "ABC Institution") }
let(:institution_child) {FactoryGirl.create(:institution, name: "Sub Institution", ancestry: institution.id) }

Style: 2

let(:institution){ FactoryGirl.create(:institution, name: "ABC Institution") }
let(:institution_child) {FactoryGirl.create(:institution, name: "Sub Institution", parent_id: institution.id) }

Style: 3

describe Institution do
  before do
    @institution = Institution.create({:institution, name: "ABC Institution"})
    @institution_child = Institution.create(:institution, name: "Sub Institution"}
  end

  it "should create the child institution" do
    assigns(:institution_child).should be_a_new(Institution)
    assigns(:institution_child).parent_id.should eq @institution.id
  end
end

I have searched for examples of Rails Ancestry testing using RSpec but haven't found anything quite useful. If anyone has any working solution or sources that they could point me to, it will be very helpful. Thanks in advance.

1

There are 1 best solutions below

2
On

Option 1, using nested factories:

factory :institution do
  sequence(:name) { |n| "ABC Institution" }

  factory :institution_child do |f|
    # f.sequence(:name) { |n| "Here you can override name for child" }
    f.parent FactoryGirl.create(:institution)
  end
end

Now in specs, you can just call :institution_child factory, too create it with parent:

describe Institution do
  let!(:institution_child) {FactoryGirl.create(:institution_child, name: "Sub Institution") }

  it "should create the child institution" do
    assigns(:institution_child).should eq institution_child
    assigns(:institution_child).parent.should eq institution_child.parent

    # just for test
    institution_child.parent.should_not be_nil
  end
end

Option 2, using traits:

factory :institution do
  sequence(:name) { |n| "ABC Institution" }

  trait :with_parent do
    after(:build) do |o|
      o.parent = FactoryGirl.create(:institution) 
    end
  end
end

Now in specs you can use it like that:

describe Institution do
  let(:institution_child) {FactoryGirl.create(:institution_child,:with_parent, name: "Sub Institution") }

  #...
end