工厂是否自动在模型中运行方法?

时间:2014-05-06 16:25:23

标签: ruby-on-rails rspec factory-bot

我正在尝试为一个完美运行的模型编写测试 - 但由于某种原因,测试没有返回预期的结果。

我的模型包含:

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回调?

3 个答案:

答案 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