JUnit:测试某种类型的异常

时间:2012-04-13 12:08:23

标签: java unit-testing exception junit

我想知道我是否可以测试(使用JUnit)异常生成的特定消息被抛出而不仅仅是“是否”抛出异常。 例如,JunitTest.java代码实际上将通过测试,因为抛出了异常,但如果我还想测试异常生成的字符串是否等于:“测试异常:整数可能不是负数...” 这可能吗?

TestException.java

public class TestException extends Exception {  
    /**
     * @param message informative message about the problem found
     */
    public TestException (String message) {
        super("Test Exception: " + message);
    }
}

Test.java

public void function(Integer mustBePositive) throws TestException {
    if (mustBePositive < 0) {
        throw new TestException("Integer may not be negative..");
    }
    else {
        mustBePositive = myNum
    }
}

JunitTest.java

import org.junit.*;

public class JUnitTest {

    @Test(expected = TestException.class)
    public void functionTest() throws TestException {
        function(-1);
    }
}

7 个答案:

答案 0 :(得分:8)

注意:我认为@Matthew's answer更胜一筹。

您可以使用以下结构 - 它测试是否抛出了正确的异常(TestException.class消息是否符合预期。

@Test(expected = TestException.class)
public void test_function_negative() {
    try {
        function(-5);
    } catch (TestException ex) {
        assertEquals("Integer may not be negative..", ex.getMessage());
        throw ex;
    }
}

修改
为什么我重新抛出异常(在评论之后):下面的第一个测试通过而第二个测试没有通过。因此它增加了额外的验证层。现在,如果我在下面的代码中捕获了ExceptionB,则两个测试都将失败。

@Test
public void test1() throws ExceptionB {
    try {
        throw new ExceptionA();
    } catch (ExceptionA e) {
        assertEquals("message", e.getMessage());
    }
}

@Test(expected=ExceptionB.class)
public void test2() throws ExceptionA {
    try {
        throw new ExceptionA();
    } catch (ExceptionA e) {
        assertEquals("message", e.getMessage());
        throw e;
    }
}

public class ExceptionA extends Exception{
    @Override
    public String getMessage() {
        return "message";
    }
}
public class ExceptionB extends ExceptionA{}

答案 1 :(得分:6)

您可以使用标准JUnit TestRule ExpectedException。这允许您测试抛出异常,并测试异常附带的消息。例如:

public static class HasExpectedException {
  @Rule
  public ExpectedException thrown= ExpectedException.none();

  @Test
  public void throwsNothing() {
    // no exception expected, none thrown: passes.
  }

  @Test
  public void throwsNullPointerException() {
    thrown.expect(NullPointerException.class);
    throw new NullPointerException();
  }

  @Test
  public void throwsNullPointerExceptionWithMessage() {
    thrown.expect(NullPointerException.class);
    thrown.expectMessage("happened?");
    thrown.expectMessage(startsWith("What"));
    throw new NullPointerException("What happened?");
  }
}

expectMessage()接受String(消息的子字符串)或Matcher,因此您可以进行正则表达式检查等等。

答案 2 :(得分:2)

assertEquals("Test Exception: Integer may not be negative..", e.getMessage());

答案 3 :(得分:1)

我是这样做的:

  @Test
  public void functionTest() throws TestException {
    try {
        function(-1);
        fail("This should have thrown an exception.");
    } catch (TextException e) {
       assertEquals("exception test produced an unexpected message", EXPECTED_TEXT, e.getMessage());
    }
  }

这可能并不优雅,但它易于理解并涵盖所有基础。免责声明 - 我没有编译它。

答案 4 :(得分:1)

其他人已经指出了你可以用来测试它的结构,但是我不会测试它本身的信息,因为这可能非常脆弱。

您应该创建一个自定义异常,获取所需的所有数据,并断言数据存在。如果您真的关心该消息,那么您可以单独对异常本身进行单元测试。

鉴于你的例子:

public void function(Integer mustBePositive) throws TestException {
    if (mustBePositive < 0) {
        throw new TestException("Integer may not be negative..");
    }
    else {
        mustBePositive = myNum
    }

你可以抛出一个NegativeNumberException。如果你真的想知道这个数字是什么,你可以修改你的代码,将其作为参数:

public void function(Integer mustBePositive) throws TestException {
    if (mustBePositive < 0) {
        throw new NegativeNumberException(mustBePositive);
    }
    else {
        mustBePositive = myNum
    }

然后在你的测试中:

 @Test(expected = NegativeNumberException.class)
 public void functionTest() throws TestException {
    try {
        function(-1);
    } catch (NegativeNumberException nne) {
        assertThat(nne.getNumber(), equalTo(-1));
    }
 }

您的异常现在可以生成消息,但它认为合适,并且对该输出的更改不会影响其余的测试代码

答案 5 :(得分:1)

catch-exception是为了支持这种情况:

import static com.googlecode.catchexception.CatchException.*;

public void testFunction() throws Exception {
    verifyException(obj).function(-1);
    assertEquals("Integer may not be negative..", 
                 caughtException().getMessage());
}

答案 6 :(得分:-1)

import org.junit。 *;

公共类JUnitTest {

@Test
public void functionTest() throws TestException {
    try {
        function (-1);
        fail("");
    } catch (TestException e) {
        if (!e.getMessage().equals("Integer may not be negative..")) 
          fail("");
    }
}