我正在尝试为一个完美运行的模型编写测试 - 但由于某种原因,测试没有返回预期的结果。
我的模型包含:
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回调?
答案 0 :(得分:2)
我正在尝试为一个完美运行的模型编写测试 - 但由于某种原因,测试没有返回预期的结果。
测试未返回预期结果,因为从未调用after_validation
回调,这就是conference
属性为nil
的原因。因此@plan.conference
为零,您无法在empty?
对象上调用nil
。因此,错误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
回调。
供参考:
回调是在某些时刻被调用的方法 对象的生命周期。通过回调,可以编写代码 每当创建,保存,更新 Active Record对象时,它都会运行 从数据库中删除,验证或加载。
答案 1 :(得分: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
答案 2 :(得分:1)
我认为最明显的方式是明确这样:
it "has a conference number" do
@plan = build(:plan)
@plan.set_conference
expect(@plan.conference).not_to be_empty
end
无论如何,我不建议使用回调。我认为最好使用service objects。