2016-04-14 8 views
0

Ich versuche, ein System zum Erstellen von Artikelübersetzungen zu testen, wo es einen Self-Join auf der Publikationstabelle gibt. Ich habe eine Factory erstellt, die mehrere Übersetzungen erstellt und sie einem übergeordneten Artikel zuordnet.Factory Girl self-join werfende Validierungsfehler

Rails 5 mit factory_girl Mit 4.7.0, rspec und Database_cleaner

Alle Aktionen wie erwartet, aber einen Test schaffen, ist das Problem

Hier die relevanten Modellvalidierungen und Methoden:

# 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 

Factory (irrelevant Code weggelassen):

# 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 

Und ein Basistest:

# 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 

Schließlich ist der Fehler:

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

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

Der erste Test bestanden (und die Veröffentlichung Objekt mit Übersetzungen erstellt korrekt), aber jeder nachfolgender Test fehlschlägt. Das Problem ist, dass ich eine Eindeutigkeitsvalidierung auf translation_id habe und es scheint, dass factorygirl versucht, die generierten Übersetzungen zu einer bereits existierenden Publikation hinzuzufügen, anstatt eine völlig neue Publikation zu erstellen.

Jede Hilfe wird geschätzt!

Antwort

0

Gelöst!

Das Problem war, dass der Sequenz-Iterator in der translation-Factory nach jedem Test nicht auf 0 zurückgesetzt wurde. Nach Test 1 begann es also, auf einen Array-Index zuzugreifen, der nicht existierte. Nachdem es das noch einmal getan hat, hat es die Validierung ausgelöst und die Tests sind fehlgeschlagen!

Die Lösung ist nicht nett, aber es ist gut genug für den Augenblick

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 
Verwandte Themen