2013-08-20 7 views
22

ich eine Klasse erhalten haben, ist, dass die Basis einiger anderer Klassen, die das Verhalten spezialisiert:Testing einfach STI mit factory

class Task < ActiveRecord::Base 
    attr_accessible :type, :name, :command 
    validates_presence_of :type, :name, :command 

    # some methods I would like to test 

end 

Die Klasse CounterTask von Aufgabe erbt

class CounterTask < Task 
end 

Das alles funktioniert Gut, bis ich versuche, die Basisklasse zu testen, da sie einen Typ haben muss.

FactoryGirl.define do 
    factory :task do 
    sequence(:name) { |n| "name_#{n}" } 
    sequence(:command) { |n| "command_#{n}" } 
    end 
end 

Wie würden Sie die grundlegende Funktionalität der Superklasse testen?

+3

Sollte Ihr Test nicht so geschrieben werden, dass er die Funktionalität testet, anstatt die Implementierung? In diesem Fall würde das bedeuten, dass Sie testen würden, ob "CounterTask" die Attribute und andere Dinge hat, die es von "Task" erhält. Wenn Sie Ihre Implementierung ändern, zum Beispiel nicht mehr mit STI. Ihr Test könnte immer noch erfolgreich sein, wenn Ihre CounterTask das gleiche Verhalten hat. – Arjan

+0

Das ist ein guter Punkt. Ich dachte nur, ich werde einige Duplikate im Test speichern, wenn ich zuerst die Basisfunktionalität und dann die Kindklassen teste ... Vielleicht könnte dies die Lösung für mein Problem sein. – Mark

Antwort

48

Sie können die Definitionen von Fabriken wie folgt erklären:

FactoryGirl.define do 
    factory :task, class: 'Task' do 
    shop 
    currency 
    value 10 
    end 

    factory :counter_task, parent: :task, class: 'CounterTask' do 
    end 
end 

Und jetzt können Sie Basisklasse getrennt von seiner eigenen Fabrik und die gleiche für jede geerbte Klasse testen.

+2

Ich musste nur die Option 'class' an die untergeordnete Factory übergeben, um dies zu ermöglichen:' factory: counter_task, Klasse: 'CounterTask' do '(für die übergeordnete Factory war auch keine' class'-Option erforderlich). – gabe

+0

@gabe Das Auslassen der 'class: 'Task'' funktioniert auch bei mir, aber' parent:: task' scheint signifikant zu sein, wenn die im Taskblock definierten Eigenschaften bei der Verwendung von counter_task definiert werden sollen. Also, mit "Eltern:: Aufgabe", "Build (: counter_task) .value == 10". Wenn Sie das übergeordnete Element nicht festlegen, "Build (: counter_task) .value == nil". – LiamD