Domanda

Supponiamo di avere un ActiveRecord::Observer in una delle tue applicazioni Ruby on Rails: come testare questo osservatore con rSpec?

È stato utile?

Soluzione

Sei sulla strada giusta, ma mi sono imbattuto in una serie di frustranti errori di messaggio imprevisti durante l'utilizzo di rSpec, osservatori e oggetti fittizi.Quando sto testando le specifiche del mio modello, non voglio dover gestire il comportamento dell'osservatore nelle aspettative dei miei messaggi.

Nel tuo esempio, non esiste un modo davvero valido per specificare "set_status" sul modello senza sapere cosa gli farà l'osservatore.

Pertanto, mi piace usare il Plug-in "Nessun guardone". Dato il codice riportato sopra e utilizzando il plugin No Peeping Toms, specificherei il modello in questo modo:

describe Person do 
  it "should set status correctly" do 
    @p = Person.new(:status => "foo")
    @p.set_status("bar")
    @p.save
    @p.status.should eql("bar")
  end
end

Puoi specificare il codice del tuo modello senza doverti preoccupare che ci sia un osservatore là fuori che entrerà e ostacolerà il tuo valore.Lo specificheresti separatamente in person_observer_spec in questo modo:

describe PersonObserver do
  it "should clobber the status field" do 
    @p = mock_model(Person, :status => "foo")
    @obs = PersonObserver.instance
    @p.should_receive(:set_status).with("aha!")
    @obs.after_save
  end
end 

Se vuoi VERAMENTE VERAMENTE testare la classe accoppiata Modello e Osservatore, puoi farlo in questo modo:

describe Person do 
  it "should register a status change with the person observer turned on" do
    Person.with_observers(:person_observer) do
      lambda { @p = Person.new; @p.save }.should change(@p, :status).to("aha!)
    end
  end
end

Il 99% delle volte preferisco eseguire il test delle specifiche con gli osservatori spenti.È semplicemente più facile così.

Altri suggerimenti

Disclaimer:In realtà non l'ho mai fatto in un sito di produzione, ma sembra che un modo ragionevole sarebbe usare oggetti finti, should_receive e amici, e invocare metodi direttamente sull'osservatore

Dato il seguente modello e osservatore:

class Person < ActiveRecord::Base
  def set_status( new_status )
    # do whatever
  end
end

class PersonObserver < ActiveRecord::Observer
  def after_save(person)
    person.set_status("aha!")
  end
end

Vorrei scrivere una specifica come questa (l'ho eseguita e passa)

describe PersonObserver do
  before :each do
    @person = stub_model(Person)
    @observer = PersonObserver.instance
  end

  it "should invoke after_save on the observed object" do
    @person.should_receive(:set_status).with("aha!")
    @observer.after_save(@person)
  end
end

no_peeping_toms ora è un gioiello e può essere trovato qui: https://github.com/patmaddox/no-peeping-toms

Se si desidera verificare che l'osservatore osservi il modello corretto e riceva la notifica come previsto, ecco un esempio utilizzando RR.

tuo_modello.rb:

class YourModel < ActiveRecord::Base
    ...
end

tuo_modello_osservatore.rb:

class YourModelObserver < ActiveRecord::Observer
    def after_create
        ...
    end

    def custom_notification
        ...
    end
end

tuo_modello_osservatore_spec.rb:

before do
    @observer = YourModelObserver.instance
    @model = YourModel.new
end

it "acts on the after_create notification"
    mock(@observer).after_create(@model)
    @model.save!
end

it "acts on the custom notification"
    mock(@observer).custom_notification(@model)
    @model.send(:notify, :custom_notification)
end
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top