Factory Girl自行加入抛出验证错误

时间:2016-04-14 18:38:01

标签: ruby-on-rails testing rspec factory-bot ruby-on-rails-5

我试图测试一个用于创建文章翻译的系统,其中在publication表上有自联接。我创建了一个工厂,该工厂将创建多个翻译并将其与父母关联起来'制品

将Rails 5与factory_girl 4.7.0,rspec和Database_cleaner一起使用

所有操作都按预期工作,但创建测试是问题

以下是相关的模型验证和方法:

  # models/publication.rb

  has_many :translations, class_name: "Publication", foreign_key: "translation_id", dependent: :nullify
  belongs_to :translation, class_name: "Publication", optional: true

  validates :language, uniqueness: { scope: :translation_id }, if: :is_translation?

  def is_translation?
    !translation.nil?
  end

工厂(省略不相关的代码):

  # spec/factories/publication.rb
  factory :publication, aliases: [:published_pub] do
    title 'Default Title'
    language 'EN'
    published

    after(:build) do |object|
      create(:version, publication: object)
    end

    #-- This is where I suspect the problem stems from

    trait :with_translations do
      association :user, factory: :random_user

      after(:build) do |object|
        create_list(:translation, 3, {user: object.user, translation:object})
      end
    end
  end

  factory :translation, class: Publication do
    sequence(:title) { |n| ['French Article', 'Spanish Article', 'German Article', 'Chinese Article'][n]}
    sequence(:language) { |n| ['FR', 'ES', 'DE', 'CN'][n]}
    user
  end

基本测试:

    # spec/models/publication_spec.rb
    before(:each) do
      @translation_parent = create(:publication, :with_translations)
      @pub_without_trans = create(:publication, :with_random_user)
    end

    scenario 'is_translation?' do
      # No actual test code needed, this passes regardless
    end

    scenario 'has_translations?' do
      # No actual test code needed, this (and subsequent tests) fail regardless
    end

最后,错误:

 Failure/Error: create_list(:translation, 3, {user: object.user, translation:object})

 ActiveRecord::RecordInvalid:
   Validation failed: Language has already been taken

第一个测试通过(并且正确创建了具有翻译的发布对象),但任何后续测试都失败。问题是我有一个作为translation_id的唯一性验证,看来factorygirl正在尝试将生成的翻译添加到现有的出版物中,而不是创建一个全新的出版物。

感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

解决!

问题是translation工厂中的序列迭代器在每次测试后没有重置为0。因此,在测试1之后,它开始尝试访问不存在的数组索引。在它再次执行之后,它触发了验证并且测试失败了!

解决方案并不可爱,但暂时还不错

sequence(:language) do |iteration|
  array = ['FR', 'ES', 'DE', 'CN']
  # Returns a number between 0 and array.length
  array[iteration%array.length]
end
sequence(:title) do |iteration|
  array = ['French Article', 'Spanish Article', 'German Article', 'Chinese Article']
  # Returns a number between 0 and array.length
  array[iteration%array.length]
end