我写了一些测试用例来测试一些方法。但是有些方法会抛出异常。我这样做了吗?
private void testNumber(String word, int number) {
try {
assertEquals(word, service.convert(number));
} catch (OutOfRangeNumberException e) {
Assert.fail("Test failed : " + e.getMessage());
}
}
@Test
public final void testZero() {
testNumber("zero", 0);
}
如果我通过-45
,它将失败并显示OutOfRangeException
,但我无法测试@Test(Expected...)
答案 0 :(得分:47)
意外的异常是测试失败,因此您既不需要也不想捕获它。
@Test
public void canConvertStringsToDecimals() {
String str = "1.234";
Assert.assertEquals(1.234, service.convert(str), 1.0e-4);
}
直到service
没有抛出IllegalArgumentException
,因为str
中有一个小数点,这将是一个简单的测试失败。
预期的异常应由expected
的可选@Test
参数处理。
@Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
service.convert(null);
}
如果程序员懒惰并抛出Exception
,或者他service
返回0.0
,则测试将失败。只有NPE
才能成功。请注意,预期异常的子类也有效。这对于NPE
来说很少见,但与IOException
和SQLException
相同。
在极少数情况下,您要测试特定的异常消息,请使用新的ExpectedException
JUnit @Rule
。
@Rule
public ExpectedException thrown= ExpectedException.none();
@Test
public void messageIncludesErrantTemperature() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("-400"); // Tests that the message contains -400.
temperatureGauge.setTemperature(-400);
}
现在,除非setTemperature抛出IAE
并且消息包含用户尝试设置的温度,否则测试将失败。此规则可以更复杂的方式使用。
您的示例最好通过以下方式处理:
private void testNumber(String word, int number)
throws OutOfRangeNumberException {
assertEquals(word, service.convert(number));
}
@Test
public final void testZero()
throws OutOfRangeNumberException {
testNumber("zero", 0);
}
您可以内联testNumber
;现在,它没有多大帮助。您可以将其转换为参数化测试类。
答案 1 :(得分:22)
删除try-catch块并将throws Exception
添加到您的测试方法中,例如:
@Test
public final void testZero() throws Exception {
assertEquals("zero", service.convert(0));
}
JUnit期望失败的测试会抛出异常,捕获它们只会阻止JUnit正确报告它们。这样,@ Test注释的预期属性也可以使用。
答案 2 :(得分:7)
您无需捕获异常即可使测试失败。只需放手(通过声明throws
),无论如何都会失败。
另一种情况是当你真正期望异常时,你会在try块结束时放入失败。
例如:
@Test
public void testInvalidNumber() {
try {
String dummy = service.convert(-1));
Assert.fail("Fail! Method was expected to throw an exception because negative numbers are not supported.")
} catch (OutOfRangeException e) {
// expected
}
}
您可以使用此类测试来验证您的代码是否正确验证了输入并处理了无效输入,但有正确的例外。
答案 3 :(得分:3)
您可以使用多种策略来处理测试中的预期异常。我认为上面已经提到过JUnit注释和try / catch习语。我想提请注意Lambda表达式的Java 8选项。
例如:
class DummyService {
public void someMethod() {
throw new RuntimeException("Runtime exception occurred");
}
public void someOtherMethod(boolean b) {
throw new RuntimeException("Runtime exception occurred",
new IllegalStateException("Illegal state"));
}
}
你可以这样做:
@Test
public void verifiesCauseType() {
// lambda expression
assertThrown(() -> new DummyService().someOtherMethod(true))
// assertions
.isInstanceOf(RuntimeException.class)
.hasMessage("Runtime exception occurred")
.hasCauseInstanceOf(IllegalStateException.class);
}
请查看此博客,其中包含大多数选项和示例。
http://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html
这个更全面地解释了Java 8 Lambda选项:
http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html