Mauvaise forme pour que le test JUnit lance une exception?

Je suis plutôt nouveau sur JUnit et je ne sais pas vraiment quelles sont les meilleures pratiques pour la gestion des exceptions et des exceptions.

Par exemple, disons que j’écris des tests pour une classe IPAddress. Il a un constructeur IPAddress (Ssortingng addr) qui lancera une exception InvalidIPAddressException si addr est null. Pour autant que je sache, le test du paramètre null ressemblera à ceci.

@Test public void testNullParameter() { try { IPAddress addr = new IPAddress(null); assertTrue(addr.getOctets() == null); } catch(InvalidIPAddressException e) { return; } fail("InvalidIPAddressException not thrown."); } 

Dans ce cas, try / catch a du sens car je sais que l’exception arrive.

Mais maintenant, si je veux écrire testValidIPAddress (), il y a plusieurs façons de le faire:

Way # 1:

 @Test public void testValidIPAddress() throws InvalidIPAddressException { IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets(); assertTrue(octets[0] == 127); assertTrue(octets[1] == 0); assertTrue(octets[2] == 0); assertTrue(octets[3] == 1); } 

Way # 2:

 @Test public void testValidIPAddress() { try { IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets(); assertTrue(octets[0] == 127); assertTrue(octets[1] == 0); assertTrue(octets[2] == 0); assertTrue(octets[3] == 1); } catch (InvalidIPAddressException e) { fail("InvalidIPAddressException: " + e.getMessage()); } } 

Est-ce que la pratique courante consiste à renvoyer des exceptions inattendues à JUnit ou à les gérer vous-même?

Merci pour l’aide.

En fait, l’ancien style de test des exceptions consiste à enrouler un bloc try autour du code qui génère l’exception, puis à append une instruction fail() à la fin du bloc try. Quelque chose comme ça:

 public void testNullParameter() { try { IPAddress addr = new IPAddress(null); fail("InvalidIPAddressException not thrown."); } catch(InvalidIPAddressException e) { assertNotNull(e.getMessage()); } } 

Ce n’est pas très différent de ce que vous avez écrit mais:

  1. Votre assertTrue(addr.getOctets() == null); est inutile.
  2. L’intention et la syntaxe sont plus claires IMO et donc plus faciles à lire.

C’est quand même un peu moche. Mais c’est là que JUnit 4 vient à la rescousse car le test des exceptions est l’une des plus grandes améliorations de JUnit 4. Avec JUnit 4, vous pouvez maintenant écrire votre test comme ceci:

 @Test (expected=InvalidIPAddressException.class) public void testNullParameter() throws InvalidIPAddressException { IPAddress addr = new IPAddress(null); } 

Nice, n’est-ce pas?

Maintenant, en ce qui concerne la vraie question, si je ne m’attends pas à ce qu’une exception soit lancée, je choisirais définitivement la méthode n ° 1 (parce qu’elle est moins verbeuse) et laisser JUnit gérer l’exception et échouer au test comme prévu.

Pour les tests où je ne m’attends pas à une exception, je ne prends pas la peine de l’attraper. Je laisse JUnit attraper l’exception (elle le fait de manière fiable) et ne répond pas du tout au-delà de la déclaration des causes (si nécessaire).

Je note re. Votre premier exemple est que vous n’utilisez pas l’annotation @expected .

 @Test (expected=IndexOutOfBoundsException.class) public void elementAt() { int[] intArray = new int[10]; int i = intArray[20]; // Should throw IndexOutOfBoundsException } 

Je l’utilise pour tous les tests que je teste pour lancer des exceptions. C’est plus court que le modèle catch / fail équivalent que j’ai dû utiliser avec Junit3.

Depuis JUnit 4.7, vous avez la possibilité d’utiliser une règle ExpectedException et vous devez l’utiliser. La règle vous donne la possibilité de définir exactement la méthode appelée où l’exception doit être générée dans votre code de test. De plus, vous pouvez facilement associer une chaîne au message d’erreur de l’exception. Dans votre cas, le code ressemble à ceci:

  @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void test() { //working code here... expectedException.expect(InvalidIPAddressException.class); IPAddress addr = new IPAddress(null); } 

MISE À JOUR: Dans son livre Practical Unit Testing avec JUnit et Mockito, Tomek Kaczanowski conteste l’utilisation d’ExceptionException, car la règle “rompt le stream arrang / act / assert” d’un test unitaire (il suggère d’utiliser Catch Exception Bibliothèque à la place). Bien que je puisse comprendre son argument, je pense que l’utilisation de la règle est correcte si vous ne voulez pas introduire une autre bibliothèque tierce (utiliser la règle est mieux que d’attraper l’exception “manuellement” de toute façon).

Pour le test null, vous pouvez simplement faire ceci:

 public void testNullParameter() { try { IPAddress addr = new IPAddress(null); fail("InvalidIPAddressException not thrown."); } catch(InvalidIPAddressException e) { } } 

Si l’exception a un message, vous pouvez également vérifier ce message dans la capture si vous le souhaitez. Par exemple

 Ssortingng actual = e.getMessage(); assertEquals("Null is not a valid IP Address", actual); 

Pour le test valide, vous n’avez pas besoin d’attraper l’exception. Un test échouera automatiquement si une exception est lancée et non interceptée. Ainsi, le n ° 1 serait tout ce dont vous avez besoin car il échouera et la trace de la stack sera à votre disposition pour votre plus grand plaisir.

Si je comprends votre question, la réponse est soit – préférence personnelle.

Personnellement, je jette mes exceptions dans les tests. à mon avis, un test qui échoue par assertion est équivalent à un test échoué par une exception non interceptée. les deux montrent quelque chose qui doit être corrigé.

L’important à retenir dans les tests est la couverture du code.

De manière générale, le n ° 1 est la voie à suivre, il n’y a pas de raison d’appeler une erreur sur une erreur – de toute façon, le test a essentiellement échoué.

Si vous avez besoin d’un bon message sur ce qui a mal tourné, la seule façon dont le temps est le bon sens et la seule exception ne vous le donnera pas. Alors attraper et échouer peut avoir un sens pour mieux annoncer la raison de l’échec.

Reg: Test des exceptions
Je suis d’accord avec “Pascal Thivent”, c’est-à-dire utiliser @Test (expected=InvalidIPAddressException.class)


Reg: Test de testValidIPAddress

 IPAddress addr = new IPAddress("127.0.0.1"); byte[] octets = addr.getOctets(); 

Je voudrais écrire un test comme

 class IPAddressTests { [Test] public void getOctets_ForAValidIPAddress_ShouldReturnCorrectOctect() { // Test code here } } 

Le point est quand testinput est VALID ipAddress
Le test doit être sur les méthodes / capacités publiques de la classe en affirmant qu’elles fonctionnent comme excepté

IMO, il est préférable de gérer l’exception et d’afficher la messagerie appropriée à partir du test plutôt que de la lancer à partir d’un test.