Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a clean way to test ActiveRecord callbacks in Rspec?

Suppose I have the following ActiveRecord class:

class ToastMitten < ActiveRecord::Base
  before_save :brush_off_crumbs
end

Is there a clean way to test that :brush_off_crumbs has been set as a before_save callback?

By "clean" I mean:

  1. "Without actually saving", because
    • It's slow
    • I don't need to test that ActiveRecord correctly handles a before_save directive; I need to test that I correctly told it what to do before it saves.
  2. "Without hacking through undocumented methods"

I found a way that satisfies criteria #1 but not #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
like image 215
Nathan Long Avatar asked Oct 24 '12 14:10

Nathan Long


1 Answers

Use run_callbacks

This is less hacky, but not perfect:

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

Using this technique to test for an after_save would be more awkward.

like image 78
Nathan Long Avatar answered Oct 15 '22 17:10

Nathan Long