57 votes

Mauvaise forme pour que le test JUnit génère une exception?

Je suis assez nouveau à JUnit, et je ne sais pas vraiment ce que les meilleures pratiques sont des exceptions et la gestion des exceptions.

Par exemple, disons que je suis en train d'écrire des tests pour une adresse ip de classe. Il a un constructeur IPAddress(String addr) qui permettra de jeter un InvalidIPAddressException si addr est null. Aussi loin que je peux dire de googler autour, le test pour le 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 parce que je sais que l'exception est à venir.

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

Façon n ° 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);
}

Chemin #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 est de pratique courante de jeter exceptions inattendues à JUnit ou simplement de traiter avec vous-même?

Merci pour l'aide.

93voto

Pascal Thivent Points 295221

En fait, l'ancien style de l' exception de test consiste à placer un bloc try autour du code qui lève l'exception, puis ajouter un fail() déclaration à la fin du bloc try. Quelque chose comme ceci:

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 de l'OMI et donc plus facile à lire.

Pourtant, c'est un peu moche. Mais c'est là que JUnit 4 vient à la rescousse, comme exception test est l'une des plus grandes améliorations dans JUnit 4. Avec JUnit 4, vous pouvez maintenant écrire votre essai comme ceci:

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

Nice, n'est-ce pas?

Maintenant, concernant la vraie question, si je ne m'attends pas la levée d'une exception, je serais certainement aller pour le chemin n ° 1 (parce que c'est moins clair) et laissez JUnit gérer l'exception et ne passent pas le test comme prévu.

10voto

Brian Agnew Points 143181

Pour les tests où je n'attends pas une exception, je ne vous embêtez pas à l'attraper. Je laisse JUnit intercepter l'exception (il le fait de façon fiable), et de ne pas répondre à tous, au-delà de déclarer l' throws cause (si nécessaire).

Je note ré. votre premier exemple que vous n'êtes pas faire usage de l' @expected d'annotation viz.

@Test (expected=IndexOutOfBoundsException.class) public void elementAt() {
    int[] intArray = new int[10];

    int i = intArray[20]; // Should throw IndexOutOfBoundsException
  }

- Je l'utiliser pour tous les tests que je suis en essais pour lever des exceptions. Il est de plus courte durée que l'équivalent de la prise/l'échec modèle que j'ai eu à utiliser avec Junit3.

9voto

s106mo Points 711

Depuis JUnit 4.7, vous avez la possibilité d'utiliser un ExpectedException la règle et vous devez l'utiliser. La règle vous donne la possibilité de définir exactement la méthode appelée lorsque l'exception doit être levée dans votre code de test. En outre, vous pouvez facilement correspondre à une chaîne de contre le 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 Pratique de Tests Unitaires avec JUnit et MockitoTomek Kaczanowski fait valoir à l'encontre de l'utilisation de ExpecetedExcpetion, parce que la règle des "sauts de les organiser/act/assert [...] flux" d'une Unité de test (il suggère d'utiliser des Captures d'Exception de la Bibliothèque de la place). Même si je peux comprendre son argument, je pense à l'aide de la règle est très bien si vous ne voulez pas introduire un autre de la 3e partie de la bibliothèque (à l'aide de la règle, c'est mieux que d'attraper l'exception "à la main" de toute façon).

0voto

digiarnie Points 4894

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 contient un message, vous pouvez également vérifier ce message dans la capture si vous le souhaitez. Par exemple

 String 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 levée et non interceptée. Donc, la solution n ° 1 serait tout ce dont vous avez besoin, car elle échouera et la trace de la pile sera disponible pour le plaisir des yeux.

0voto

pstanton Points 8807

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

Personnellement, je lance mes exceptions dans les tests. à mon avis, un test qui échoue par affirmation équivaut à un test qui échoue par une exception non interceptée. les deux montrent quelque chose qui doit être corrigé.

la chose importante à retenir lors des tests est la couverture de code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X