2010-10-28 12 views
8

Ich habe folgende Fabriken:Factory Girl Fehler mit has_many Beziehung

Factory.define :email do |email| 
    email.email {"infomcburney.cowan.com"} 
end 

Factory.define :lead do |lead| 
    lead.emails {|emails| [emails.association(:email)]} 
end 

, die die folgenden Klassen modelliert werden

class Lead < ActiveRecord::Base 
    has_many :emails 
end 

class Email < ActiveRecord::Base 
    belongs_to :lead, :class_name => "Lead", :foreign_key => "lead_id" 
end 

Wenn ich die diesen Test durch shoulda laufen:

should "capture emails" do 
     lead = Factory.build(:lead) 
     assert_equal(1, lead.emails.size) 
    end 

Ich erhalte den folgenden Fehler:

Factory::AttributeDefinitionError: Attribute already defined: emails

Ich bin völlig darauf fest, kann mir jemand in die richtige Richtung zeigen. Ich benutze factory_girl 1.3.2.

+0

Point of style: Fabriken Platzhalter-Daten und nichts anderes enthalten sollen. Alles, was für Sie bei der Verwendung von Bedeutung sein sollte, ist, dass ein gültiger Lead generiert wird, und Sie sollten davon ausgehen, dass sich die tatsächliche Anzahl der an den Lead angehängten E-Mails ändern kann. Wenn Ihr Test von einer bestimmten Anzahl von Leads abhängt, erstellen Sie den Lead ab Werk und legen Sie die E-Mails explizit fest. – Matchu

Antwort

9

Ich würde empfehlen, has_many Beziehungsdaten zu Ihren Fabriken hinzuzufügen. Der Grund dafür ist, dass Ihre Lead-Factory jetzt davon abhängt, diese Verbindung zu füllen, und sie fügt mehr Kopplung hinzu und möglicherweise einige Verwirrung auf der Straße, wenn sich die Verbindung ändert.

Wenn Sie diese Beziehung testen möchten (und ich empfehle es Ihnen), gibt es ein großes Juwel namens Shoulda, das Unit Test-Makros hinzufügt, um sicherzustellen, dass die Beziehungen richtig eingerichtet sind. Ich habe es nicht mit dem eingebauten in Rails-Test :: Unit verwendet, aber ein RSpec Beispiel würde in etwa so aussehen:

describe Lead do 
    it { should have_many(:emails) } 
end 

Wenn Sie wirklich, diese Beziehung testen wollen, sollten Sie es in der Spezifikation tun. Entfernen Sie die E-Mails Vereinigung von Ihrem Lead Factory und erstellen Sie ein Lead-Objekt und versuchen Sie es Objekte ein paar E-Mail wie so weitergeben müssen:

lead = Factory.build(:lead) 
2.times do { lead.emails << Factory.build(:email, :lead => lead) } 

Dann sollte es ein paar E-Mails zusammen mit ihm haben. Sie sollten jedoch Vertrauen in ActiveRecord setzen und nur Dinge testen, die über das hinausgehen, was Rails bereits für Sie tut. Dies ist, wo Shoulda kommt.

Ein weiterer Kommentar, den ich habe, ist auf Ihre E-Mail-Beziehungen gehört. Da Sie nur die Standardkonventionen verwenden, weiß rails, was zu tun ist.

class Email < ActiveRecord::Base 
    belongs_to :lead 
end 
+0

Vielen Dank für Ihre Antwort, aber was ist, wenn ich eine Fabrik namens lead_with_one_email möchte, weil ich sie immer so erstellen muss, wie Sie es oben tun? Sicherlich macht es Sinn, das in der Fabrik zu tun, um den Erstellungscode zu reduzieren? Es scheint, dass dies möglich sein sollte? – dagda1

+0

Wenn alle Lead-Tests mindestens eine E-Mail erfordern, ist dies ein Problem. Sie sollten Ihr Führungsmodell unabhängig von anderen Modellen testen können. Möglicherweise müssen Sie dazu Mocks und Stubs verwenden. Wenn Sie jedoch nur eine Teilmenge von Tests haben, die Sie mit einer E-Mail testen möchten, würde ich eine Gruppe erstellen, die dieses Verhalten isoliert.In Rspec heißt diese Gruppe entweder einen Describe- oder einen Context-Block und isoliert einige Tests, die ein bestimmtes Setup (z. B. eine E-Mail) erfordern. –

Verwandte Themen