ruby-on-rails - test - rspec rails 5
¿Cómo evaluarías a los observadores con rSpec en una aplicación Ruby on Rails? (4)
Supongamos que tiene un ActiveRecord :: Observer en una de sus aplicaciones de Ruby on Rails: ¿cómo prueba este observador con rSpec?
Descargo de responsabilidad: nunca he hecho esto en un sitio de producción, pero parece que una forma razonable sería usar objetos simulados, should_receive
y friends, e invocar 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
Escribiría una especificación como esta (la ejecuté y pasó)
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
Está en el camino correcto, pero me he encontrado con una cantidad de frustrantes errores de mensajes inesperados al usar rSpec, observadores y objetos simulados. Cuando estoy probando la especificación de mi modelo, no quiero tener que manejar el comportamiento del observador en las expectativas de mi mensaje.
En su ejemplo, no hay una manera realmente buena de especificar "set_status" en el modelo sin conocimiento de lo que el observador le hará.
Por lo tanto, me gusta utilizar el complemento "No Peeping Toms". Dado su código anterior y utilizando el complemento No Peeping Toms, especifico el modelo así:
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
Puedes especificar el código de tu modelo sin tener que preocuparte de que haya un observador que vaya a entrar y arruinar tu valor. Deberías especificar eso por separado en 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 REALMENTE REALMENTE desea probar la clase acoplada Model y Observer, puede hacerlo así:
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
99% del tiempo, preferiría probar con los observadores apagados. Es más fácil de esa manera.
Si desea probar que el observador observa el modelo correcto y recibe la notificación como se esperaba, aquí hay un ejemplo que usa 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
no_peeping_toms ahora es una joya y se puede encontrar aquí: https://github.com/patmaddox/no-peeping-toms