How can I create factories for circular association in FactoryGirl?

I had problems creating factories for some of the objects and associations that I defined in my project. I have a cyclic association where an object is associated with two other objects that are subsequently combined.

+--------------+ +-------------+ | | | | | TestCase +---------> | TestDataGrid| | | | | +------+-------+ +------+------+ | | | | | | vv +--------------+ +--------------+ | | | | | | | | | TestVariable | | TestDataSet | | | | | +------+-------+ +------+-------+ | | | | | | | | | +---------------+ | | | | | | | | | +---> | TestDataValue |<---+ | | +---------------+ 

 class TestCase < ActiveRecord::Base has_many :test_variables, dependent: :destroy has_many :test_data_grids #...omitted code... end class TestVariable < ActiveRecord::Base belongs_to :test_case has_many :test_data_values #...omitted code... end class TestDataValue < ActiveRecord::Base belongs_to :test_variable belongs_to :test_data_set #...omitted code... end class TestDataSet < ActiveRecord::Base belongs_to :test_data_grid has_many :test_data_values #...omitted code... end class TestDataGrid < ActiveRecord::Base belongs_to :test_case has_many :test_data_sets #...omitted code... end 

Basically the association breaks up in TestCase and connects again in TestDataValue, how can I create a Factory that opens and closes the circle with the same objects?

+6
source share
3 answers

This is not verified, but:

 FactoryGirl.define do factory :test_data_value do test_data_set test_variable # attributes end factory :test_data_set do test_data_grid # attributes end factory :test_variable do test_case # attributes end factory :test_case do # attributes end factory :test_data_grid do test_case # attributes end end 

Then in the specifications:

 @test_data_value = FactoryGirl.create(:test_data_value) @test_variable = @test_data_value.test_variable @test_data_set = @test_data_value.test_data_set 
0
source

My suggestion would be to not install it in the factories, but in the tests themselves.

Factory file (thanks @ veritas1)

 FactoryGirl.define do factory :test_data_value do # attributes end factory :test_data_set do # attributes end factory :test_variable do # attributes end factory :test_case do # attributes end factory :test_data_grid do # attributes end end 

Test file

 @test_case = FactoryGirl.create(:test_case) @test_data_grid = FactoryGirl.create(:test_case) @test_variable = FactoryGirl.create(:test_case) @test_data_set = FactoryGirl.create(:test_case) @test_data_value = FactoryGirl.create(:test_case) @test_case.test_data_grids << @test_data_grid @test_case.test_variables << @test_variable @test_data_grid.test_data_set << @test_data_set @test_variable.test_data_values << @test_data_value @test_data_set.test_data_values << @test_data_value 

I know this may suck a little, but it sounds like a way to do it. However, as a thought, if you are struggling with your trials, this is usually a sign that you will be fighting with him along the highway, and you must redesign the API. I do not see an alternative way to do this, but you may be able with domain knowledge.

0
source

You can do it manually:

 test_case = FactoryGirl.build(:test_case) test = FactoryGirl.build(:test_data_value, :test_variable => FactoryGirl.build(:test_variable, :test_case => test_case ), :test_data_set => FactoryGirl.build(:test_data_set, :test_data_grid => FactoryGirl.build(:test_data_grid, :test_case => test_case ) ) ) test.test_variable.test_case == test.test_data_set.test_data_grid.test_case # => true 

Or write an auxiliary factory:

 FactoryGirl.define do factory :test_data_value do ignore do test_case nil test_data_grid nil end test_variable do build :test_variable, :test_case => test_case || test_data_grid.try(:test_case) || build(:test_case) end test_data_set do build :test_data_set, :test_data_grid => test_data_grid || ( build :test_data_grid, :test_case => test_case || build(:test_case) ) end end end 

Test version as a common ancestor:

 test = FactoryGirl.create :test_data_value, :test_case => FactoryGirl.build(:test_case) test.test_variable.test_case == test.test_data_set.test_data_grid.test_case # => true 

Test case as a common ancestor and the same test_data_grid for each instance:

 test_data_grid = FactoryGirl.build :test_data_grid, :test_case => FactoryGirl.build(:test_case) test = FactoryGirl.create :test_data_value, :test_data_grid => test_data_grid test.test_variable.test_case == test.test_data_set.test_data_grid.test_case # => true 
0
source

Source: https://habr.com/ru/post/924866/


All Articles