2012-10-24 7 views
6

Supponiamo che io ho la seguente classe ActiveRecord:C'è un modo pulito per testare i callback di ActiveRecord in Rspec?

class ToastMitten < ActiveRecord::Base 
    before_save :brush_off_crumbs 
end 

C'è un modo pulito per verificare che :brush_off_crumbs è stato impostato come un before_save richiamata?

Con "pulito" Voglio dire:

  1. "Senza in realtà il risparmio", perché
    • E 'lento
    • Non ho bisogno di testare che ActiveRecord correttamente gestisce una direttiva before_save; Ho bisogno di testare che ho correttamente detto cosa fare prima di salvare.
  2. "Senza l'hacking attraverso metodi non documentati"

ho trovato un modo che soddisfa i criteri # 1, ma non # 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 

risposta

9

Usa run_callbacks

Questo è meno hacky , ma non perfetto:

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 

L'utilizzo di questa tecnica per verificare un after_save sarebbe più complicato.

+0

questo è il modo più elegante che abbia mai visto! molte grazie! – rickypai

+0

C'è qualcosa come "run_callbacks' per i callback dei controller? – Dennis

+2

Per un 'after_save', probabilmente potresti semplicemente inserire' should_receive' all'interno del blocco e restituire true, cioè 'revenue_object.run_callbacks (: save) do; revenue_object.should_receive (: record_financial_changes); vero; fine' –

Problemi correlati