2010-10-28 115 views
8

我有以下工厂:工厂女孩误差的has_many关系

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

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

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

哪些是模拟以下类

class Lead < ActiveRecord::Base 
    has_many :emails 
end 

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

当我通过早该运行该测试

我收到以下错误:

Factory::AttributeDefinitionError: Attribute already defined: emails

我完全被卡住这一点,任何人都可以点我在正确的方向。我正在使用factory_girl 1.3.2。

+0

的风格上看:工厂应该包含占位符数据而已。所有这些对你来说都很重要,因为使用它们会产生有效的潜在客户,并且你应该假设附属于潜在客户的电子邮件的实际数量可能会发生变化。如果您的测试依赖于一定数量的线索,请从工厂建立线索,然后明确设置电子邮件。 – Matchu 2010-10-28 23:39:36

回答

9

我会建议不要加入的has_many关系数据到你的工厂。原因在于您的主要工厂现在依赖于填充此关联关系,并且如果关联发生变化,则会增加更多关联并可能会导致一些混淆。

如果你想测试这种关系(我建议你这样做),有一个叫Shoulda的巨大宝石添加了单元测试宏以确保关系设置正确。我还没有与内置在Rails中的Test ::单位使用,但一个RSpec例子看起来是这样的:

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

如果你真的想测试这种关系,你应该这样做的规范。从铅厂取出邮件协会,并创建一个铅对象,并试图通过它像这样一些电子邮件的对象:

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

那么它应该有它几封电子邮件联系。然而,你应该对ActiveRecord有一些信心,并且只是测试一些超出Rails已经为你做的事情。这是早该进来。

另一评论我是你的电子邮件belongs_to的关系。既然你只是使用默认的约定,rails会知道该怎么做。

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

谢谢您的回复,但是如果我想要一个名为lead_with_one_email的工厂,因为我总是需要像上面那样创建它?在工厂能够做到这一点是有道理的,以减少重复创建代码? 这似乎应该是可能的? – dagda1 2010-10-29 04:53:56

+0

如果您的所有潜在客户测试都需要至少一封电子邮件,那么这是一个问题。您应该能够独立于任何其他型号测试您的主导模型。您可能需要为此使用模拟和存根。但是,如果您只有一部分要通过电子邮件测试的测试,我会创建一个组来隔离此行为。在Rspec中,这个组被称为描述或上下文块,它隔离了一些需要特定设置(如电子邮件)的测试。 – 2010-10-29 05:26:05