3

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

测试异常.java

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

测试.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);
    }
}
4

7 回答 7

8

注意:我认为@Matthew 的回答更好。

您可以使用以下结构 - 它测试是否抛出了正确的异常 ( 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{}
于 2012-04-13T12:14:00.550 回答
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()接受字符串(消息的子字符串)或匹配器,因此您可以进行正则表达式检查或其他任何操作。

于 2012-04-13T18:40:51.750 回答
2
assertEquals("Test Exception: Integer may not be negative..", e.getMessage());
于 2012-04-13T12:12:14.643 回答
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));
    }
 }

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

于 2012-04-13T12:24:45.353 回答
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());
}
于 2012-06-22T15:54:41.033 回答
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());
    }
  }

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

于 2012-04-13T12:14:30.693 回答
-1

导入 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("");
    }
}
于 2012-04-13T12:14:41.427 回答