Oui, je sais, que tester des méthodes privées n'est pas une bonne idée (et j'ai lu ce fil - http://www.Ruby-forum.com/topic/197346 - et quelques autres)
Mais comment puis-je tester le code suivant?
J'utilise xmpp4r. Dans ma méthode publique #listen
Je commence à recevoir des messages Jabber comme ceci:
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
- exécute le bloc, lorsque le message arrive (dans un fil différent)
Donc, tester #listen
la méthode est difficile et teste plus xmpp4r que mon #do_things_with_message
Comment bien faire et tester #do_things_with_message
? :) ( http://www.Ruby-forum.com/topic/197346#859664 )
Refactoriser les méthodes privées vers un nouvel objet l'essentiel serait que je les rende public (et classe avec une méthode - c'est insensé
EDIT: Il s'agit plus d'une question théorique sur le code propre et les tests corrects. Dans mon premier lien, les gens soutiennent que les méthodes privées de test sont mal. Je ne veux pas tricher avec #send
, mais je ne vois aucun moyen viable de refactoriser
Vous pouvez appeler une méthode privée dans Ruby en utilisant la méthode send
. Quelque chose comme ceci:
@my_object = MyObject.new
@my_object.send(:do_things_with_message, some_message)
Dans un test qui ressemblerait à quelque chose comme:
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
En laissant de côté la question de savoir si vous devriez tester une méthode privée, il est très possible dans Ruby pour rendre temporairement une méthode privée publique. Voici ce que je veux dire:
# 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
Vous utiliseriez publicize_methods
comme ça:
ClassToTest.publicize_methods do
...
do_private_things_with_message(m).should ???
...
end
Vous avez probablement entendu cette pensée dans toutes les ressources que vous mentionnez, mais la bonne façon "théorique" de le faire serait de tester que @client
reçoit add_message_callback
, puis testez indirectement vos méthodes privées avec des tests d'intégration. L'intérêt des tests unitaires est que vous pouvez modifier l'implémentation, et vos tests réussiront toujours