如何在junit中处理exception
我写了一些测试用例来测试一些方法。 但是有些方法会抛出exception。 我做得对吗?
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
但我无法测试特定的exception,如@Test(Expected...)
意外的exception是测试失败,因此您既不需要也不想捕获它。
@Test public void canConvertStringsToDecimals() { String str = "1.234"; Assert.assertEquals(1.234, service.convert(str), 1.0e-4); }
直到service
没有抛出IllegalArgumentException
因为str
有一个小数点,这将是一个简单的测试失败。
预期的exception应该由@Test
的可选expected
参数处理。
@Test(expected=NullPointerException.class) public void cannotConvertNulls() { service.convert(null); }
如果程序员懒惰并抛出Exception
,或者他的service
返回0.0
,则测试将失败。 只有NPE
才能成功。 请注意,预期exception的子类也有效。 这对于NPE
很少见,但与IOException
和SQLException
。
在极少数情况下,您要测试特定的exception消息,请使用新的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
; 现在,它没有多大帮助。 您可以将其转换为参数化测试类。
删除try-catch块并向测试方法添加throws Exception
,如:
@Test public final void testZero() throws Exception { assertEquals("zero", service.convert(0)); }
JUnit期望失败的测试将抛出exception,捕获它们只是阻止JUnit能够正确报告它们。 这样,@ Test注释的预期属性也可以使用。
您不需要捕获exception以使测试失败。 只是放手(通过宣布throws
)它无论如何都会失败。
另一种情况是,当您实际期望exception时,则在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 } }
您可以使用此类测试来validation您的代码是否正确validation输入并使用适当的exception处理无效输入。
您可以使用几种策略来处理测试中的预期exception。 我认为上面已经提到过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