在JUnit4中,您可以通过在一个方法中提供参数集合来编写参数化单元测试,该方法将被传递给测试的构造函数并在另一个方法中进行测试。如果我有一个我希望抛出异常的参数,我该如何指定?
答案 0 :(得分:22)
这是我如何使用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;
}
}
答案 1 :(得分:5)
与其他建议相比,我不会在测试中引入任何逻辑 - 即使是简单的ifs!
你应该拥有两种测试方法:
不确定JUnit及其基于构造函数的参数化测试是否能够执行此操作。可能你必须为此创建两个测试类。使用JUnit Params或TestNG,它提供了更方便的解决方案。
答案 2 :(得分:4)
if (parameter == EXCEPTION_EXPECTED) {
try {
method(parameter);
fail("didn't throw an exception!");
} catch (ExpectedException ee) {
// Test succeded!
}
}
答案 3 :(得分:1)
Gabriel,请查看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() {
}
}
另一种方法是使用JUnit 4.7中的ErrorCollector: @规则 public ExpectedException thrown = ExpectedException.none();
@Test
public void testCollectingErrors() {
thrown.handleAssertionErrors();
thrown.expect(MultipleFailureException.class); // or #expectMessage()/#expectCause()
collector.checkThat("a", equalTo("b"));
//...
}
答案 4 :(得分:0)
如果您使用catch-exception而不是JUnit4的相应注释和规则,那么您的代码将如下所示:
catchException(obj).method(parameter);
if (parameter != EXCEPTION_EXPECTED) {
assert caughtException() instanceof ExpectedException;
}
// more assertions
答案 5 :(得分:0)
我同意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);
});
}
如果您想提供多个参数,则可以使用 MethodSource 和 ValueSource 进行测试。
答案 6 :(得分:0)
@Test(expected = Exception.class)
@Parameters(value = { "invalidInput1", "invalidInput2" })
public void shouldThrowOnInvalidInput(String input) {
ClassToTest.methodToTest(input);
}
使用junitparams。来自junitparams库的参数。