如何测试after_initialize轨道模型的回调?

时间:2011-09-13 07:47:17

标签: ruby-on-rails ruby-on-rails-3 rspec rspec2 rspec-rails

我正在使用FactoryGirl和Rspec进行测试。 如果为零,则模型在init之后设置外键。因此它使用另一个关联的数据。但我怎么测试呢? 通常我会使用工厂来创建这个对象,并使用stub_chain作为“self.user.main_address.country_id”。但是在创建此对象后,将调用initialize。我没有机会把它留下来。

after_initialize do
  if self.country_id.nil?
    self.country_id = self.user.main_address.country_id || Country.first.id
  end
end

有什么想法吗?

3 个答案:

答案 0 :(得分:8)

理想情况下,测试行为而不是实现更好。测试是否设置了外键而不是测试该方法是否被调用。

虽然,如果您想测试after_initialize回调,这是一种有效的方法。

obj = Model.allocate
obj.should_receive(:method_here)
obj.send(:initialize)

Allocate将对象放入内存但不调用initialize。设置期望后,您可以调用initialize并捕获方法调用。

答案 1 :(得分:5)

奥兰多的方法有效,而这是我想添加的另一种方法。 (使用新的rspec'期望'语法)

expect_any_instance_of(Model).to receive(:method_here)
Model.new

答案 2 :(得分:0)

另一种方法是重构代码以允许进行简单的单元测试。照原样,您的代码已接近我在回调中输入的代码量的上限:

curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFileName); 
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieFileName);

如果增长更多,我将其提取到一个方法中,并将您的回调减少为一个方法调用:

after_initialize do
  if self.country_id.nil?
    self.country_id = self.user.main_address.country_id || Country.first.id
  end
end

这里的好处是,测试after_initialize :init_country_id def init_country_id if self.country_id.nil? self.country_id = self.user.main_address.country_id || Country.first.id end end 成为此时的另一种方法单元测试……对此一无所知。

现在您已经对行为进行了单元测试,如果您有疑问,还可以测试它是否被调用。 (像init_country_id这样简单的事情不需要进行调用测试,IMO)

您可以使用gem shoulda-callback-matchers来测试您的回调实际上已按预期触发:

after_initialize :init_country_id