Как проверить исключения в параметризованном тесте? - PullRequest
13 голосов
/ 11 ноября 2010

В JUnit4 вы можете написать параметризованные модульные тесты, обеспечив сбор параметров в одном методе, который будет передан конструктору теста, а тестирование - другим методом. Если у меня есть параметр, для которого я ожидаю, что будет сгенерировано исключение, как мне это указать?

Ответы [ 6 ]

22 голосов
/ 27 марта 2016

так я использую параметризованный тест junit с ожидаемыми исключениями:

@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;
}
}
5 голосов
/ 20 сентября 2012

В отличие от того, что предлагают другие, я бы не стал вводить какую-либо логику в тесты - даже простые ifs!

То, что вы должны иметь, это два метода тестирования:

  • firstодин принимает допустимые параметры (и ожидает некоторый вывод)
  • секунда принимает недопустимые параметры (и ожидает исключения)

Не уверен, что JUnit с его параметризованным тестированием на основе конструктора сможет это сделать,Возможно, вам придется создать два тестовых класса для этого.Используйте JUnit Params или TestNG, которые предлагают гораздо более удобное решение.

4 голосов
/ 11 ноября 2010
if (parameter == EXCEPTION_EXPECTED) {
    try {
        method(parameter);
        fail("didn't throw an exception!");
    } catch (ExpectedException ee) {
        // Test succeded!
    }
}
1 голос
/ 02 июля 2014

Габриэль, пожалуйста, посмотрите на правило TestWatcher (начиная с JUnit 4.9). Вот пример кода, цитируемый из 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() {
     }
 }

Другой подход заключается в использовании ErrorCollector из JUnit 4.7: @Rule public ExpectedException thrown = ExpectedException.none ();

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

    collector.checkThat("a", equalTo("b"));
    //...
}
0 голосов
/ 26 сентября 2018

Я согласен с Томеком и хотел бы пройти два теста. Первые тесты для случаев, когда никаких исключений не ожидается. Второй проверяет значения, которые должны приводить к генерированию исключений (т. Е. Завершаться сбоем, если они не выбрасываются).

Ниже приведен простой пример, в котором реализация ExceptionThrower.throwAnInstanceException (int) просто генерирует IllegalArgumentException , когда значение int меньше единицы В вашей реализации все предоставленные значения должны вызывать исключение.

@ParameterizedTest
@ValueSource(ints = {0, 1})
public void parameterizedIntExceptionTest(int testValue) {
    ExceptionThrower exceptionThrower = new ExceptionThrower();

    assertThrows(IllegalArgumentException.class, () -> {
        exceptionThrower.throwAnInstanceException(testValue);
    });
}

Если вы хотите указать несколько аргументов, вам следует использовать MethodSource недостаток ValueSource для теста.

0 голосов
/ 22 июня 2012

Если бы вы использовали catch-exception вместо соответствующих аннотаций и правил JUnit4, тогда ваш код будет выглядеть так:

catchException(obj).method(parameter);

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