如何在参数化测试中测试异常?

Gab*_*bák 15 java junit unit-testing parameterized junit4

在JUnit4中,您可以通过在一个方法中提供参数集合来编写参数化单元测试,该方法将被传递给测试的构造函数并在另一个方法中进行测试.如果我有一个我希望抛出异常的参数,我该如何指定?

Yar*_*rix 26

这是我如何使用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;
}
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*ski 7

与其他建议相反,我不会在测试中引入任何逻辑 - 即使是简单的ifs!

您应该拥有两种测试方法:

  • 第一个采用有效参数(并期望一些输出)
  • 第二个采用无效参数(并期望例外)

不确定JUnit是否能够执行此基于构造函数的参数化测试.可能你必须为此创建两个测试类.使用JUnit Params或TestNG,它提供了更方便的解决方案.


SoC*_*Cal 6

我同意 Tomek 的观点,并会进行两次测试。第一次测试没有异常的情况。第二个测试应该导致抛出异常的值(即,如果没有抛出则失败)。

下面是一个简单的例子,当提供的 int 小于 1 时,ExceptionThrower.throwAnInstanceException(int)的实现只是抛出一个IllegalArgumentException。在您的实现中,所有提供的值都应触发异常。

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

    assertThrows(IllegalArgumentException.class, () -> {
        exceptionThrower.throwAnInstanceException(testValue);
    });
}
Run Code Online (Sandbox Code Playgroud)

如果您想提供多个参数,那么你会看使用MethodSource副一ValueSource进行测试。


Ben*_*ine 5

if (parameter == EXCEPTION_EXPECTED) {
    try {
        method(parameter);
        fail("didn't throw an exception!");
    } catch (ExpectedException ee) {
        // Test succeded!
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我希望有一个更合理的解决方案 - 例如像多个 @Parameters 方法和可选的预期注释参数,但我想这样的东西不是框架的一部分。还是很感谢你。 (3认同)