繁体   English   中英

JUnit4 @Test(expected = MyException.class)VS try / catch

[英]JUnit4 @Test(expected=MyException.class) VS try/catch

我正在考虑异常处理和单元测试最佳实践,因为我们正在努力获得一些代码最佳实践。

我们公司维基上发现的前一篇关于最佳实践的文章指出“不要使用try / catch,而是使用Junit4 @Test(expect = MyException.class)”,没有进一步的信息。 我不相信。

我们的许多自定义异常都有一个枚举,以便识别失败原因。 结果,我宁愿看到如下的测试:

@Test
public void testDoSomethingFailsBecauseZzz() {
try{
   doSomething();
} catch(OurCustomException e){
   assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ, e.getFailure());
}
}

比:

@Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
   doSomething();
}

当doSomethig()看起来像:

public void doSomething throws OurCustomException {
  if(Aaa) {
     throw OurCustomException(FailureEnum.AAA);
  } 
  if(Zzz) {
     throw OurCustomException(FailureEnum.ZZZ);
  }
  // ...
}

在旁注中,我更确信在某些情况下@Test(expected = blabla.class)是最佳选择(例如,当异常是精确的并且毫无疑问导致它的原因时)。

我在这里遗漏了什么,还是应该在必要时推动使用try / catch?

听起来你的枚举被用作异常层次结构的替代品? 也许如果你有一个异常层次结构, @Test(expected=XYZ.class)会变得更有用吗?

  • 如果您只想检查是否抛出了某种类型的异常,请使用注释的expected属性。
  • 如果要检查抛出异常的属性(例如消息或自定义成员值),请在测试中捕获它并进行断言。

在你的情况下,似乎你想要后者(断言异常有一定的FailureEnum值); 使用try/catch没有任何问题

你应该“不使用try / catch”(解释为“从不”)的概括是无聊的。

杰夫是对的; 您的异常层次结构的组织是可疑的。 但是,你似乎认识到这一点。 :)

如果要检查原始异常类型,则expected方法是合适的。 否则,如果你需要测试关于异常的一些东西(并且无论测试消息内容的enum怪异是否常见)你都可以尝试catch,但这有点老了。 新的JUnit方法是使用MethodRule API中出现的一个( ExpectedException )是专门测试消息,但是您可以轻松查看代码并调整该实现以检查失败enum

我在搜索如何处理异常时遇到了这个问题。

正如@Yishai所提到的,期望异常的首选方法是使用JUnit规则和ExpectedException

当使用@Test(expected=SomeException.class)如果在方法中的任何位置抛出异常,则测试方法将通过。

使用ExpectedException

@Test
public void testException()
{
    // If SomeException is thrown here, the test will fail.
    expectedException.expect(SomeException.class);
    // If SomeException is thrown here, the test will pass.
}

你也可以测试:

  • 预期的消息: ExpectedException.expectMessage() ;
  • 预期原因: expectedException.expectCause()

作为旁注:我不认为使用枚举来处理异常消息/原因是一种很好的做法。 (如果我错了,请纠正我。)

在您的特殊情况下,您希望测试(1)是否抛出预期的异常类型 ,以及(2)如果错误号是正确的,因为该方法可以使用不同的类型抛出相同的异常。

这需要检查异常对象。 但是,您可以坚持建议验证是否抛出了正确的异常:

@Test(expected = OurCustomException.class)
public void testDoSomethingFailsBecauseZzz() {
   try {
      doSomething();
   } catch (OurCustomException e) {
      if (e.getFailureEnum.equals(FailureEnum.ZZZ))  // use *your* method here
         throw e;

      fail("Catched OurCostomException with unexpected failure number: " 
        + e.getFailureEnum().getValue());  // again: your enum method here
   }
}

此模式将 吃掉意外的异常并使测试失败。

编辑

改变它是因为我错过了显而易见的事情:我们可以使测试用例失败并捕获消息。 所以现在:如果抛出了带有预期错误代码的预期异常,则测试通过。 如果由于我们遇到意外错误而导致测试失败,那么我们就可以读取错误代码。

我做了一个例外,因为我遇到了和你一样的问题,Stph。 使用catch-exception,您的代码可能如下所示:

@Test
public void testDoSomethingFailsBecauseZzz() {
   verifyException(myObj, OurCustomException.class).doSomething();
   assertEquals("Omg it failed, but not like we planned", FailureEnum.ZZZ,    
               ((OurCustomException)caughtException()).getFailure() ;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM