Factory Girl特质

5

在尝试编写rSpec测试时,我有点困惑如何使用FactoryGirl记录关联。

基本上,我有一个Quiz模型和一个Question模型。它们通过HABTM关联相关联。

这是我的Quiz工厂:

FactoryGirl.define do
  factory :quiz do
    description 'Test'

    # after(:create) { |quiz| quiz.create_sample_questions }

    # trait :with_questions do
    #   after :create do |quiz|
    #     5.times do |q|
    #       quiz.questions << FactoryGirl.create(:question, :with_answers)
    #     end
    #   end
    # end
  end
end

在这里创建一个trait,然后为测验创建样本问题是最好的选择吗?还是应该使用after create方法来处理呢?

似乎两种方法都不起作用,我的trait没有生成问题。

谢谢!


虽然回复晚了,但您能否发布您的“问题”工厂以及您如何使用“with_questions”特性调用“quiz”? - vee
2个回答

7
我更喜欢使用trait,因为它们使规范更简洁。当然,重要的是要确保工厂本身不会变得过于混乱。
每次我定义一个构建关联的trait时,我都会确保可以在关联中构建可变数量的记录,而FactoryGirl可以很容易地实现这一点:
FactoryGirl.define do
  factory :quiz do
    description 'Test'

    trait :with_questions do
      ignore    { question_count 5 }
      questions { build_list(:question, question_count) }
    end
  end
end

现在您可以在规格中创建或构建测验:
FactoryGirl.create(:quiz, :with_questions)
FactoryGirl.build(:quiz, :with_questions, question_count: 2)

请注意,该特性使用build_list,因此默认情况下不会保存问题,而是使用question_count而不是questions_count,以避免与计数器缓存发生冲突。
为了确保您的规范并未超出必要程度,除非验证要求它们,否则最好只构建问题而不是带有答案的问题。如果在某个时候确实需要带有答案的问题,则可以添加另一个特性:
FactoryGirl.define do
  factory :quiz do
    description 'Test'

    ignore { question_count 5 }
    trait :with_questions do
      questions { build_list(:question, question_count) }
    end

    trait :with_answered_questions do
      questions { build_list(:question, question_count, :with_answers) }
    end
  end
end

想要了解如何在FactoryGirl中使用关联,请参考FactoryGirl文档


1
看起来在factorygirl中,ignore现在被称为transient了。https://github.com/thoughtbot/factory_girl/pull/651 - tgf

3

我很想看到其他人对这个问题的回答,但我可以分享一下我使用工厂、关联和自动加载对象的个人经验。

基本上,我发现当我尝试使用特性和回调函数时,会给我的测试规范带来更多麻烦。按照这种扭曲的逻辑,你最终会得到一堆工厂的混乱,让你不知所措。

完全假设的问题:如果以后您需要一个有4个问题的测验怎么办?那么每个quiz :with_questions 都包括5个问题。您是否要创建一个名为with_4_questions的特性?;)

根据我的经验,我建议您从在规范中生成单独的模型开始,并保持简单。不要将太多逻辑抽象到回调函数后面。

因此,假设我正在使用您的模型编写一个功能规范,以下是我如何实现您想要完成的任务:

feature 'User edits a question' do
  let!(:quiz) { FactoryGirl.create(:quiz) }

  before do
    5.times { FactoryGirl.create(:question, quiz: quiz) }
  end

  scenario 'with valid input' do
    # ...
  end
end

如果你经常需要一个包含5个问题的测验,你可以使用Railscasts演示的方法创建一个 , 至少这样你可以创建一个可以传入参数的方法,比如我上面的完全假设性问题中的 num_questions。请保留HTML标签。

谢谢,这真的很有帮助! - Paul
我发布了一种不同的方法,也以不同的方式回答了你完全假设的问题。 - fivedigit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接