2016-04-14 68 views
0

我試圖測試一個系統來創建文章翻譯在出版物表上有一個自我連接。我創建了一個工廠,可以創建多個翻譯並將它們與「父」文章相關聯。工廠女孩自動加入丟擲驗證錯誤

使用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試圖將生成的翻譯添加到已存在的發佈中,而不是創建一個全新的發佈。

任何幫助表示讚賞!

回答

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