¿Cómo evaluarías los observadores con rSpec en una aplicación de Ruby on Rails?
-
09-06-2019 - |
Pregunta
Supongamos que usted tiene un ActiveRecord::Observador en uno de sus Ruby on Rails aplicaciones - ¿cómo se prueba este observador con rSpec?
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