2013-03-27 1 views
2

Je vous écris une application Socket Java, où un serveur prend des messages à partir d'une notification EventSource et l'envoi aux utilisateurs connectés, en fonction du eventtype.JUnit meilleures pratiques - les méthodes d'essai, où le résultat ne peut pas être vérifiée avec des méthodes publiques

Maintenant, je suis sur le point d'écrire des tests JUnit pour le serveur ... JUnit (dans Eclipse suggère automatiquement) pour implémenter des tests pour toutes les méthodes publiques et j'en vois la nécessité. La classe server a une méthode publique bufferEvent ..., mais les événements sont gérés dans des méthodes privées et il n'y a même pas de méthode qui renvoie le nombre de messages mis en mémoire tampon.

Ainsi, le serveur ne dispose pas de méthodes publiques pour vérifier le résultat.

Je pense que le problème peut être généralisé: Comment puis-je tester les méthodes publiques, où le résultat ne peut pas être vérifiée avec des méthodes publiques (sans etc. getter)

Je veux éviter d'écrire des méthodes supplémentaires juste pour les tests. Existe-t-il une solution de contournement ou une meilleure pratique pour tester ces éléments?

Merci d'avance

+0

Probablement la réflexion pourrait aider? – Petr

+0

http://stackoverflow.com/questions/10141626/changing-private-methods-to-protected-for-testing – andersoj

+0

pouvez-vous fournir votre code? Nous avons des coachs TDD dans notre société et ils nous ont expliqué quelques astuces, mais les varient en fonction du code source. Parfois, vous n'avez pas à tester les résultats de la méthode, mais juste pour vérifier si certains appels sont correctement effectués. Parfois, vous avez un défaut de conception et la méthode privée devrait en réalité résider dans une autre classe et être publique et donc testable. – ThanksForAllTheFish

Répondre

1

Vous pouvez vérifier le scénario de test négatif. Il n'y a pas de retour du service, mais peut-être il y a une exception qui est lancée par le service:

@Test 
public void testServerService(){ 
try{ 
    myServer.service(); 
    Assert.assertTrue(true); 
}catch(Exception ex){ 
    Assert.fail("anything goes wrong"); 
} 
} 

Sinon, dans ce cas j'écrire quelque chose comme ceci:

@Test 
public void testServerService(){ 
    myServer.service(); 
    Assert.assertTrue(true); 
} 

donc je dois au moins assertion pour vérifier si le processus s'exécute sans problèmes.

btw Je pense que vous avez raison. écrire de nouvelles fonctionnalités juste pour vérifier les tests de Junit est une très mauvaise pratique.

+0

'Assert.assertTrue (true)' est une instruction redondante. Le test se terminera sans succès. Si vous attendez et exception, utilisez '@Test (expected = YourException.class)' ou si vous ne vous y attendez pas, lancez l'exception. JUnit imprimera l'échec pour vous. – Alex

+0

Salut Stefan, merci d'avoir souligné que je devrais éviter les fonctions supplémentaires. C'est un exercice de test pour une application. Et le code devrait suivre les meilleures pratiques ... :) Si bon que je n'ai pas commencé à le faire – ramin

2

Vous devriez faire un constructeur qui vous permet d'insérer des simulacres ou des espions pour les collaborateurs.

Par exemple, votre serveur aurait un constructeur Server(List<Buffer> buffer). Seulement utilisé pour les tests. Ensuite, vous pouvez ajouter le tampon dans le test unitaire et affirmer que des modifications sont apportées à ce tampon.

La liste est assez facile à remplacer par un objet que vous créez dans le test. Si vous voulez des choses plus avancées, jetez un oeil à un cadre moqueur comme Mockito.

Par exemple, vous créez un simulacre pour un socket. Vous obtiendriez Socket = mock(Socket.class. Vous insérez dans le constructeur Server(List<Buffer> buffer, Socket socket). Ensuite, après avoir appelé la fonction que vous voulez tester, vous pouvez vérifier le comportement en utilisant par exemple verify(socket).send("yourMessage") pour voir si le serveur a utilisé la méthode send avec les paramètres "yourMessage".

Par exemple this Plugins class nécessite des plugins dans son constructeur. Pour tester son les mocks sont créés, insérés et ensuite vérifié in this test class comme ceci: verify(proxyServerPlugin).proxyServer(config);.

Voir la Mockito pour plus d'exemples.

+0

Salut Alex, merci d'utiliser des sons mock bien. Je devrais créer un constructeur pour ajouter quelques objets fantaisie juste pour tester, mais en faisant cela, je pourrais au moins, tester plusieurs fonctions, en ajoutant tous les mocks nécessaires à la construtcor – ramin

+0

Pour être sûr, vous pouvez ajouter '@ VisibleForTesting' annotation par Google Guice pour dire aux autres développeurs le constructeur est seulement là pour les tests. Bien entendu, vous devez également protéger le paquet constructor pour vous assurer que personne n'en abuse. – Alex

+0

ça sonne aussi bien. Malheureusement, je suis censé ne pas utiliser de bibliothèques tierces, car il s'agit d'un test d'application exersice ... – ramin

0

Que pensez-sur l'ajout d'un enregistreur, avec ses propres valeurs importantes Test de niveau, Loggin à la fin des méthodes et ayant un flux à A testclass.

+0

ok ce n'était pas une bonne idée. Les réflexions fonctionnent très bien! – ramin

Questions connexes