2010-11-11 33 views
8

Dans JUnit4, vous pouvez écrire des tests unitaires paramétrés en fournissant une collection de paramètres dans une méthode, qui sera transmise au constructeur du test et testée dans une autre méthode. Si j'ai un paramètre pour lequel je m'attends à ce qu'une exception soit levée, comment puis-je le spécifier?Comment tester des exceptions dans un test paramétré?

Répondre

4
if (parameter == EXCEPTION_EXPECTED) { 
    try { 
     method(parameter); 
     fail("didn't throw an exception!"); 
    } catch (ExpectedException ee) { 
     // Test succeded! 
    } 
} 
+2

J'espériez une solution plus raisonnable - par exemple quelque chose comme plusieurs méthodes @Parameters avec l'argument d'annotation attendu facultatif, mais je suppose que quelque chose comme ça ne fait pas partie du framework. Merci quand même. –

0

Si vous avez utilisé catch-exception au lieu des annotations et des règles correspondantes de junit4, alors votre code ressemblerait à ceci:

catchException(obj).method(parameter); 

if (parameter != EXCEPTION_EXPECTED) { 
    assert caughtException() instanceof ExpectedException; 
} 
// more assertions 
5

Contrairement à ce que d'autres suggèrent, je ne présenterait aucune sorte de logique aux tests - même si simple!

Ce que vous devriez avoir sont deux méthodes d'essai:

  • premier prend des paramètres valides (et attend une sortie)
  • secondes prend des paramètres non valides (et attend des exceptions)

Je ne sais pas si JUnit avec ses tests paramétrés basés sur le constructeur est capable de le faire. Probablement, vous devrez créer deux classes de test pour cela. Aller avec JUnit Params ou TestNG qui offrent une solution beaucoup plus pratique.

1

Gabriel, regardez la règle TestWatcher (depuis JUnit 4.9). Voici l'exemple de code cité http://junit-team.github.io/junit/javadoc/4.11/org/junit/rules/TestWatcher.html:

public static class WatchmanTest { 
    private static String watchedLog; 

    @Rule 
    public TestWatcher watchman= new TestWatcher() { 
     @Override 
     protected void failed(Throwable e, Description description) { 
      watchedLog+= description + "\n"; 
     } 

     @Override 
     protected void succeeded(Description description) { 
      watchedLog+= description + " " + "success!\n"; 
     } 
    }; 


    @Test 
    public void fails() { 
     fail(); 
    } 

    @Test 
    public void succeeds() { 
    } 
} 

Une autre approche serait d'utiliser ErrorCollector de JUnit 4.7: @Rule ExpectedException publique jeté = ExpectedException.none();

@Test 
public void testCollectingErrors() { 
    thrown.handleAssertionErrors(); 
    thrown.expect(MultipleFailureException.class); // or #expectMessage()/#expectCause() 

    collector.checkThat("a", equalTo("b")); 
    //... 
} 
13

c'est comment j'utiliser le test JUnit paramétrés avec des exceptions prévues:

@RunWith(Parameterized.class) 
public class CalcDivTest { 

@Parameter(0) 
public int num1; 
@Parameter(1) 
public int num2; 

@Parameter(2) 
public int expectedResult; 

@Parameter(3) 
public Class<? extends Exception> expectedException; 
@Parameter(4) 
public String expectedExceptionMsg; 

@Rule 
public ExpectedException thrown = ExpectedException.none(); 

@Parameters 
public static Iterable<Object[]> data() { 
    return Arrays.asList(new Object[][] { 
     // calculation scenarios: 
     { 120, 10, 12, null, null }, // simple div 
     { 120, 0, -1, ArithmeticException.class, "/ by zero" }, // div by zero   
    }); 

} 

@Test 
public void testDiv() throws CCalculationException { 

    //setup expected exception 
    if (expectedException != null) { 
     thrown.expect(expectedException); 
     thrown.expectMessage(expectedExceptionMsg); 
    } 

    assertEquals("calculation result is not as", expectedResult, div(num1, num2)); 

} 

private int div(int a, int b) { 
    return a/b; 
} 
}