在factory_girl中填充与子项的关联

时间:2010-05-30 02:34:52

标签: ruby-on-rails ruby unit-testing factory factory-bot

我有一个模型Foo has_many'Bar'。我为每个对象都有一个factory_girl工厂。 Bar的工厂与Foo有关联;它会在创建Bar时实例化Foo。

我想要一个创建包含Bar的Foo的Factory。理想情况下,这个Bar将通过:bar工厂创建,并尊重用于创建Foo的构建策略(创建/构建)。

我知道我可以调用:bar工厂,然后从新的Bar中获取Foo引用。我想避免这种情况;在我的测试用例中,重要的对象是Foo;称酒吧工厂似乎有点迂回曲折。此外,我可以看到需要一个具有多个条形的Foo。

这可能在factory_girl吗?你如何在父母中定义这种关系?

5 个答案:

答案 0 :(得分:50)

Factory.after_ hooks似乎是唯一成功完成此操作的方法。我找到了一种方法来维护构建策略而不重复代码:

Factory.define :foo do |f|
  f.name "A Foo"
  f.after(:build) { |foo|
    foo.bars << Factory.build(:bar, :foo => foo)
  }
  f.after(:create) { |foo|
    foo.bars.each { |bar| bar.save! }
  }
end

如果使用after_build构建策略,则documentation表示after_create将在:create之前调用。如果使用:build,则只会调用after_build,并且每个人都很满意。

我还创建了一个抽象的通用版本at this gist来保持干净。

答案 1 :(得分:4)

您可以双向使用association方法:

Factory.define :foo do |f|
  # ...
  f.association :bar
end

如果这不起作用,您可以使用回调手动关联它们。以下是我的一个应用程序的示例:

Factory.define :live_raid do |raid|
end

Factory.define :live_raid_with_attendee, :parent => :live_raid do |raid|
  raid.after_create { |r| Factory(:live_attendee, :live_raid => r) }
end

答案 2 :(得分:3)

FactoryGirl现在有一个:method => :build选项,您可以在关联上使用它,它将构建关联对象而不是创建它。

#64: Building an object creates associations

答案 3 :(得分:3)

FactoryGirl 4.3.0在父对象上调用save!时正在关联上调用build,我认为这不是正确的行为。

在挖掘FactoryGirl代码后,将strategy: :build添加到工厂中的关联定义似乎现在正在创建我的关联而不调用save!

答案 4 :(得分:2)

使用factory_girl-4.5.0,在父对象工厂中创建n个子对象

FactoryGirl.define do
  factory :foo do
    name "test"        

    after(:build) do |instance|
      n.times { instance.bars << FactoryGirl.create(:bar) }          
    end
  end
end