【问题标题】:JUnit: Testing for an exception of certain typeJUnit:测试某种类型的异常
【发布时间】:2012-04-25 19:10:45
【问题描述】:

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

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);
    }
}

【问题讨论】:

标签: java unit-testing exception junit


【解决方案1】:
assertEquals("Test Exception: Integer may not be negative..", e.getMessage());

【讨论】:

    【解决方案2】:

    注意:我认为@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{}
    

    【讨论】:

    • 谢谢你这正是我所追求的:)
    • 在这种情况下应该是 assertTrue。
    • 它工作正常,但我已经修改为你的版本更好。
    • 在代码中声明异常类会燃烧我的灵魂,然后必须在@Test中再次这样做。
    • @TonyEnnis 你的灵魂很热;)
    【解决方案3】:

    我是这样做的:

      @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】:

      导入 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("");
          }
      }
      

      【讨论】:

      • 如果你打算这样做,你应该使用 assertEquals 或 assertThat。如果此测试失败,则没有关于原因的输出
      【解决方案5】:

      其他人已经指出了您可以用来测试的结构,但我不会测试消息本身,因为这可能很脆弱。

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

      举个例子:

      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));
          }
       }
      

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

      【讨论】:

      • 如果字符串很重要,我会测试它。除非字符串是动态的,否则我不会认为这样的测试比任何其他测试都更脆弱。在任何情况下,字符串都应该是 TestJava 中的公共常量。然后测试(和实际代码)可以引用常量。
      • 如果字符串足够重要以进行测试,那么将其作为测试代码和生产代码都引用的常量会导致毫无意义的测试。然后,您要测试的是它们引用了相同的字符串,但没有任何东西可以验证实际字符串是否正确
      【解决方案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() 接受字符串(消息的子字符串)或匹配器,因此您可以进行正则表达式检查或其他任何操作。

      【讨论】:

        【解决方案7】:

        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());
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-01-28
          • 2020-08-07
          • 1970-01-01
          • 2013-02-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多