ruby - tests - rspec tutorial
Prueba de método privado en Ruby(rspec) (3)
Dejando de lado la cuestión de si deberías probar un método privado, es muy posible que Ruby haga público temporalmente un método privado. Esto es lo que quiero decir:
# Metaprogrammatical magic to temporarily expose
# a Class'' privates (methods).
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public *saved_private_instance_methods }
yield
self.class_eval { private *saved_private_instance_methods }
end
end
Utilizaría publicize_methods
así:
ClassToTest.publicize_methods do
...
do_private_things_with_message(m).should ???
...
end
Esta pregunta ya tiene una respuesta aquí:
- Cómo especificar un método privado 3 respuestas
Sí, lo sé, probar métodos privados no es una buena idea (y leo este hilo - http://www.ruby-forum.com/topic/197346 - y algunos otros)
Pero, ¿cómo puedo probar el siguiente código?
Yo uso xmpp4r. En mi método público #listen
empiezo a recibir mensajes de jabber de esta manera:
def listen
@client.add_message_callback do |m|
do_things_with_message(m)
end
end
private
def do_things_with_message(m)
#
end
#add_message_callback
- ejecuta el bloqueo, cuando #add_message_callback
mensaje (en un hilo diferente)
Por lo tanto, probar el método #listen
es difícil y probar más xmpp4r que mi #do_things_with_message
¿Cómo hacerlo bien y probar #do_things_with_message
? :) ( http://www.ruby-forum.com/topic/197346#859664 )
Refactorizar los métodos privados a un nuevo objeto sería esencialmente como hacerlos públicos (y clase con un método: es sin sentido
EDITAR: Esta es más una pregunta teórica sobre el código de limpieza y las pruebas correctas. En mi primer enlace, la gente argumenta que la prueba de métodos privados es mala. No quiero hacer trampa con #send
, pero tampoco veo ninguna forma viable de refactorizar
Probablemente hayas escuchado este pensamiento en todos los recursos que mencionas, pero la forma "teórica" correcta de hacerlo sería probar que @client
recibe add_message_callback
, y luego prueba indirectamente tus métodos privados con pruebas de integración. El objetivo de las pruebas unitarias es que puede cambiar la implementación, y sus pruebas aún pasarán
Puede llamar a un método privado en ruby utilizando el método de send
. Algo como esto:
@my_object = MyObject.new
@my_object.send(:do_things_with_message, some_message)
En una prueba que se vería algo así como:
it "should do a thing" do
my_object = MyObject.new
my_object.send(:do_things_with_message, some_message)
my_object.thing.should == true
end