2010-10-28 10 views
8

Mam następujące fabryki:błąd Dziewczyna z fabryki z relacji has_many

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

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

które są modelowania następujące klasy

class Lead < ActiveRecord::Base 
    has_many :emails 
end 

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

Kiedy uruchamiam test ten poprzez shoulda:

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

Pojawia się następujący błąd:

Factory::AttributeDefinitionError: Attribute already defined: emails

Całkowicie utknąłem na tym, czy ktoś może wskazać mi właściwy kierunek. Używam factory_girl 1.3.2.

+0

Punkt stylu: fabryki powinny zawierać dane zastępcze i nic więcej. Wszystko, co powinno mieć dla Ciebie znaczenie podczas korzystania z nich, to wygenerowanie ważnego potencjalnego klienta, i powinieneś założyć, że rzeczywista liczba wiadomości e-mail dołączonych do potencjalnego klienta może ulec zmianie. Jeśli twój test zależy od pewnej liczby potencjalnych klientów, zbuduj lead z fabryki, a następnie ustaw jawnie wiadomości e-mail. – Matchu

Odpowiedz

9

Polecam, nie dodając danych relacji ma_many do fabryk. Powodem tego jest to, że twoja fabryka ołowiu zależy teraz od zapełnienia tego powiązania i dodaje więcej sprzężenia i potencjalnie trochę pomieszania w dół, jeśli to skojarzenie się zmieni.

Jeśli chcesz przetestować ten związek (i zalecam ci to zrobić), jest tam wielki klejnot o nazwie Shoulda, który dodaje makra testów jednostkowych, aby upewnić się, że relacje są prawidłowe. Nie używałem go z wbudowanego testu Rails :: Unit, ale przykładem RSpec będzie wyglądać następująco:

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

Jeśli naprawdę chcesz przetestować tę relację, należy to zrobić w spec. Usuń powiązanie wiadomości w Twojej fabryce ołowiu i stworzenie wiodącego przedmiotu i starają się przekazać go kilka obiektów maila tak:

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

Następnie powinien on mieć związek kilka e-maili z nim. Jednak powinieneś pokładać wiarę w ActiveRecord i po prostu testować rzeczy, które wykraczają poza to, co Rails już dla ciebie robi. To właśnie tu pojawia się Shoulda.

Kolejny komentarz, jaki mam, to adres e-mail należący do związku. Ponieważ używasz tylko domyślnych konwencji, szyny będą wiedzieć, co robić.

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

Dziękuję za odpowiedź, ale co, jeśli chcę mieć fabrykę o nazwie lead_with_one_email, ponieważ zawsze muszę ją tworzyć tak, jak robisz powyżej? Na pewno ma sens, aby móc to zrobić w fabryce, aby ograniczyć powtarzanie kodu stworzenia? Wygląda na to, że to powinno być możliwe? – dagda1

+0

Jeśli wszystkie testy wiodące wymagają co najmniej jednego e-maila, oznacza to problem. Powinieneś być w stanie przetestować swój główny model niezależnie od innych modeli. Być może będziesz musiał użyć do tego mocks i stubów. Jeśli jednak masz tylko podzbiór testów, które chcesz przetestować za pomocą wiadomości e-mail, utworzę grupę izolującą to zachowanie.W Rspec ta grupa nazywa się blokiem opisu lub kontekstu i izoluje kilka testów, które wymagają określonej konfiguracji (takiej jak wiadomość e-mail). –

Powiązane problemy