2014-05-06 15 views
0

我想为完美工作的模型编写一个测试 - 但由于某种原因测试没有返回预期的结果。工厂是否会自动在模型中运行方法?

我的模型包含此:

after_validation :set_conference 

    def rand_conference 
    r = rand.to_s[2..8] 
    while conference == r 
     r = rand.to_s[2..8] 
    end 
    r 
    end 

    def set_conference 
    self.conference = rand_conference unless conference.presence 
    end 
end 

而在我的模型试验我测试这个(理想情况下,我将测试如果“会议”是一个6位数字,但现在只是一个“不是零”就足够了):

厂:

FactoryGirl.define do 
    factory :plan do 
    name "Test" 
    description "Lorem Ipsum" 
    category "template" 
    end 
end 

Model_spec:

before (:each) do 
    @plan = build(:plan) 
    end 


it "has a conference number" do 
    expect(@plan.conference).not_to be_empty 
end 

结果我得到:

1) Plan has a conference number 
    Failure/Error: expect(@plan.conference).not_to be_empty 
    NoMethodError: 
     undefined method `empty?' for nil:NilClass 

是否factorygirl使用after_validation回调?

回答

2

我想写一个测试工作完美的模型 - 但由于某种原因测试没有返回预期的结果。

测试没有返回预期的结果,因为after_validation回调永远不会调用这就是为什么conference属性nil。所以@plan.conference是零,你不能在nil对象上调用empty?。因此,错误undefined method 'empty?' for nil:NilClass

@plan = build(:plan)只想创建Plan模型的实例按在factory :plan指定的属性,并将其分配给实例变量@plan它肯定不会运行任何验证,显然没有ActiveRecord回调。

只要改变之前块作为

before (:each) do 
    @plan = create(:plan) ## create record in database 
end 

有了这个你after_validation回调将被触发,你实际上是在数据库中创建一个记录。

参考:

回调是被调用在 对象的生命周期中的某些时刻的方法。通过回调,可以编写代码,只要活动记录对象被创建,保存,更新, 删除,验证或从数据库加载时, 将运行。

+0

问题解决了,这就实现了。加分结构非常好的解释!更进一步,还有@fivedigit的答案,它也适用。 –

+0

很高兴能帮到:) –

1

是的回调是自动运行。但是,您使用FactoryGirl.build来构建计划,该计划仅初始化对象但不验证它。

您可能需要确保验证的运行:

before (:each) do 
    @plan = build(:plan) 
end 

it "has a conference number" do 
    @plan.valid? 
    expect(@plan.conference).not_to be_empty 
end 

或者你需要调用FactoryGirl.create创建你的计划,而且这也将在您的测试数据库中创建它:

before (:each) do 
    @plan = create(:plan) 
end 

it "has a conference number" do 
    expect(@plan.conference).not_to be_empty 
end 
+0

谢谢!这也像一种魅力。你有没有机会知道什么是更快的方法 - 使用“创建”或“构建”+“有效?” ? –

+0

尽量避免“创建”,因为它们涉及I/O,因此它们使测试变得更慢。我宁愿在测试验证回调时触发验证。 – fivedigit

1

我认为最abvious的办法是明确的是这样的:

it "has a conference number" do 
    @plan = build(:plan) 
    @plan.set_conference 
    expect(@plan.conference).not_to be_empty 
end 

无论如何,我不建议使用回调。我认为最好使用service objects

+0

谢谢!我认为其他解决方案在我的情况下效果更好,因为他们使用我的验证 - 但我肯定会看看服务对象! –

相关问题