2012-10-24 100 views
6

假设我有以下的ActiveRecord类:是否有一种干净的方式来测试Rspec中的ActiveRecord回调?

class ToastMitten < ActiveRecord::Base 
    before_save :brush_off_crumbs 
end 

有没有干净的方式来测试:brush_off_crumbs已被设置为before_save回调?

通过 “干净” 我的意思是:

  1. “没有实际保存”,因为
    • 它很慢
    • 我并不需要测试ActiveRecord的正确处理一个before_save指令;我需要测试我是否正确告诉它保存之前要做什么。
  2. “没有通过无证方法黑客”

我发现满足条件#1,但不是#2的方式:

it "should call have brush_off_crumbs as a before_save callback" do 
    # undocumented voodoo 
    before_save_callbacks = ToastMitten._save_callbacks.select do |callback| 
    callback.kind.eql?(:before) 
    end 

    # vile incantations 
    before_save_callbacks.map(&:raw_filter).should include(:brush_off_crumbs) 
end 

回答

9

使用run_callbacks

这是不太哈克,但并不完美:

it "is called as a before_save callback" do 
    revenue_object.should_receive(:record_financial_changes) 
    revenue_object.run_callbacks(:save) do 
    # Bail from the saving process, so we'll know that if the method was 
    # called, it was done before saving 
    false 
    end 
end 

使用这种技术来测试after_save会更尴尬。

+0

这是我见过的最优雅的方式!非常感谢! – rickypai

+0

有没有像控制器回调的'run_callbacks'? – Dennis

+2

对于'after_save',你可能只需将'should_receive'放在块内并返回true,即:''revenue_object.run_callbacks(:save)do; revenue_object.should_receive(:record_financial_changes);真正; end' –

相关问题