Pregunta

Supongamos que usted tiene un ActiveRecord::Observador en uno de sus Ruby on Rails aplicaciones - ¿cómo se prueba este observador con rSpec?

¿Fue útil?

Solución

Usted está en el camino correcto, pero se han topado con una serie de frustrantes inesperado mensaje de errores en la utilización de rSpec, observadores, y se burlan de los objetos.Cuando estoy de especificaciones de las pruebas de mi modelo, no quiero tener que ocuparse de observador comportamiento en mi mensaje expectativas.

En tu ejemplo, no hay una manera muy buena de spec "set_status" en el modelo sin el conocimiento de lo que el observador va a hacer a él.

Por lo tanto, me gusta usar la "No hay mirones" plugin. Dado su código anterior y utilizando el voyerismo plugin, me gustaría especificación del modelo como este:

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

Usted puede especificación de su modelo de código sin tener que preocuparse de que hay un observador que es va a venir y darle una paliza a su valor.Te gustaría spec que por separado en el person_observer_spec como este:

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 

Si usted REALMENTE desea probar el Modelo acoplado y Observador de la clase, usted puede hacer esto de esta manera:

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

El 99% del tiempo, prefiero especificaciones de prueba con los observadores apagado.Es simplemente más fácil de esa manera.

Otros consejos

Descargo de responsabilidad:En realidad nunca he hecho esto en un sitio de producción, pero se ve como una manera razonable sería utilizar objetos ficticios, should_receive y amigos, y la invocación de métodos en el observador directamente

Dado el siguiente modelo y observador:

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

Me gustaría escribir una especificación como este (me corrió, y se pasa)

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 ahora es una joya y se puede encontrar aquí: https://github.com/patmaddox/no-peeping-toms

Si desea probar que el observador observa el modelo correcto y recibe la notificación como era de esperar, aquí es un ejemplo del uso de RR.

your_model.rb:

class YourModel < ActiveRecord::Base
    ...
end

your_model_observer.rb:

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

    def custom_notification
        ...
    end
end

your_model_observer_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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top