如何在junit中处理异常



我写了一些测试用例来测试一些方法。但是有些方法会抛出异常。我做对了吗?

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...)

意外异常是测试失败,因此您既不需要也不想捕获异常。

@Test
public void canConvertStringsToDecimals() {
    String str = "1.234";
    Assert.assertEquals(1.234, service.convert(str), 1.0e-4);
}

直到service没有抛出IllegalArgumentException,因为str里面有一个小数点,这将是一个简单的测试失败。

预期的异常应该由@Test的可选参数expected来处理。

@Test(expected=NullPointerException.class)
public void cannotConvertNulls() {
    service.convert(null);
}

如果程序员懒惰并抛出Exception,或者如果他让service返回0.0,测试将失败。只有NPE才能成功。注意,预期异常的子类也可以工作。这在NPE s中很少见,但在IOException s和SQLException s中很常见。

在极少数情况下,您希望测试特定的异常消息,您可以使用新的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期望失败的测试会抛出异常,你捕获它们只是阻止JUnit正确报告它们。这样,@Test注释上预期的属性也会起作用。

您不需要捕获异常以使测试失败。只要让它去(通过声明throws),它无论如何都会失败。

另一种情况是,当你真的期望出现异常时,你把fail放在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
  }
}

您可以使用这种测试来验证您的代码是否正确地验证了输入,并使用适当的异常处理了无效的输入。

您可以使用几种策略来处理测试中预期的异常。我认为JUnit注释和try/catch习惯用法已经在上面提到过了。我想提请注意Java 8的Lambda表达式选项。

例如:

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

最新更新