【问题标题】:JUnit test — analysing expected Exceptions [duplicate]JUnit 测试 — 分析预期异常 [重复]
【发布时间】:2011-05-28 05:59:53
【问题描述】:

在 JUnit 中,我目前正在使用注解来预期我的测试中会出现异常。

有没有办法分析这个异常?比如我期待一个CriticalServerException,但我也想验证getMessage方法的内容。

【问题讨论】:

    标签: java exception junit


    【解决方案1】:

    如果您有 JUnit 4.7 或更高版本,请尝试ExpectedException

    this question中有一个例子,复制如下:

    @Rule
    public ExpectedException exception = ExpectedException.none();
    
    @Test
    public void testRodneCisloRok(){
        exception.expect(IllegalArgumentException.class);
        exception.expectMessage("error1");
        new RodneCislo("891415",dopocitej("891415"));
    }
    

    【讨论】:

    • 感谢@Progman 提供此问题的链接。
    • 绝对是朝着正确方向迈出的一步
    • 感谢邓肯的编辑
    • exception对象中设置后调用方法对我来说是关键。
    【解决方案2】:

    我不确定你是否应该这样做。使用 try-catch 块来检查错误消息是如此 junit3ish。我们现在有了这个很酷的功能,您可以写 @Test(expected=CriticalServerException.class) 并且您想“返回”并再次使用 try-catch 来获取您期望的异常,只是为了检查错误消息?

    IMO 你应该留下@Test(expected=CriticalServerException.class) 注释并忽略错误消息。检查错误消息,因为它是一个更“人类可读”的字符串而不是技术值,所以可以更改很多,也可能很棘手。您正在强制异常具有特定的错误消息,但您可能不知道谁生成了异常以及他选择了什么错误消息。

    一般来说,您想测试方法是否抛出异常,而不是实际错误消息的样子。如果错误消息真的很重要,您可能应该考虑使用它抛出的异常的子类并在@Test(expected=...) 中检查它。

    【讨论】:

    • +1 以获得有用的答案;我不知道我个人是否喜欢这个,但这是一个很好的了解机制
    【解决方案3】:
    try{ 
        //your code expecting to throw an exception
        fail("Failed to assert :No exception thrown");
    } catch(CriticalServerException ex){
        assertNotNull("Failed to assert", ex.getMessage()) 
        assertEquals("Failed to assert", "Expected Message", ex.getMessage());
    }
    

    【讨论】:

    • 如果没有抛出异常,测试不会失败。
    • @Thomas Lötzer 啊是的.. 更新了。
    • 这是 JUnit 3 的正确方法。对于 JUnit 4 (
    【解决方案4】:
    try
    {
        // your code
    
        fail("Didn't throw expected exception");
    }
    catch(CriticalServerException e)
    {
        assertEquals("Expected message", e.getMessage());
    }
    

    【讨论】:

      【解决方案5】:
      try {
          // test code invacation
          fail("Exception not throw!!!");
      } catch(CriticalServerException ex) {
          assertTrue("Invalid exception data", ex.toString().contains("error text"));
      }
      

      【讨论】:

        【解决方案6】:

        如果您有很多测试用例要测试,请使用 MethodRule 作为常用解决方案

        public class ExceptionRule implements MethodRule {
            @Override
            public Statement apply(final Statement base, final FrameworkMethod method, Object target) {
                return new Statement() {
                    @Override
                    public void evaluate() throws Throwable {
                        try {
                            base.evaluate();
                            Assert.fail();
                        } catch (CriticalServerException e) {
                            //Analyze the exception here
                        }
                    }
                };    
            }
        }
        

        然后在你的测试类中使用规则:

        @Rule public ExceptionRule rule = new ExceptionRule(); 
        

        【讨论】:

          【解决方案7】:

          我认为没有办法使用注释来做到这一点。您可能不得不退回到 try-catch 方式,在 catch 块中您可以验证消息

          【讨论】:

            【解决方案8】:

            使用catch-exception:

            catchException(obj).doSomethingCritical();
            assertTrue(caughtException() instanceof CriticalServerException);
            assertEquals("Expected Message", caughtException().getMessage());
            

            【讨论】:

              【解决方案9】:

              看看fluent-exception-rule,它“结合了 Junit ExpectedException 规则和 AssertJ 的断言便利性。”

              import pl.wkr.fluentrule.api.FluentExpectedException;
              ...
              @Rule
              public FluentExpectedException thrown = FluentExpectedException.none();
              
              @Test
              public void testDoSomethingCritical() {
                  thrown.expect(CriticalServerException.class).hasMessage("Expected Message").hasNoCause();
                  obj.doSomethingCritical();
              }
              

              【讨论】:

                【解决方案10】:

                如果你想比较消息和异常类型,那么你可以试试下面的代码 sn-p。

                    @Rule
                    public ExpectedException expectedException = ExpectedException.none();
                
                    expectedException.expect(IllegalArgumentException.class);
                    expectedException.expectMessage("Parameter is not valid"); //check string contains
                    expectedException.expectMessage(CoreMatchers.equalTo("Parameter is not valid")); //check string equals
                

                注意:这将适用于 junit 4.9 以后的版本。

                【讨论】:

                  【解决方案11】:

                  Java 8 解决方案

                  这是我写的一个实用函数:

                  public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
                  {
                      try
                      {
                          runnable.run();
                      }
                      catch( Throwable throwable )
                      {
                          if( throwable instanceof AssertionError && throwable.getCause() != null )
                              throwable = throwable.getCause(); //allows "assert x != null : new IllegalArgumentException();"
                          assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
                          assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
                          @SuppressWarnings( "unchecked" )
                          T result = (T)throwable;
                          return result;
                      }
                      assert false; //expected exception was not thrown.
                      return null; //to keep the compiler happy.
                  }
                  

                  (taken from my blog)

                  如下使用:

                  @Test
                  public void testThrows()
                  {
                      RuntimeException e = expectException( RuntimeException.class, () -> 
                          {
                              throw new RuntimeException( "fail!" );
                          } );
                      assert e.getMessage().equals( "fail!" );
                  }
                  

                  另外,如果您想了解您应该检查异常消息的一些原因,请参阅:https://softwareengineering.stackexchange.com/a/278958/41811

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2013-02-19
                    • 2017-07-11
                    • 2013-11-01
                    • 1970-01-01
                    • 2018-07-20
                    • 1970-01-01
                    • 2011-01-28
                    • 2019-01-23
                    相关资源
                    最近更新 更多