问题描述
||
我正在考虑异常处理和单元测试的最佳实践,因为我们正在尝试制定一些代码最佳实践。
在我们公司的Wiki上可以找到有关最佳做法的前一篇文章,内容为“请勿使用try / catch,而应使用Junit4 @Test(expect = MyException.class)\”,而无需进一步的信息。我不相信。
我们的许多自定义异常都有一个Enum,以识别失败原因。
结果,我宁愿看到这样的测试:
@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?
解决方法
如果您只是想检查是否抛出了某种类型的异常,请使用批注的
expected
属性。
如果要检查引发的异常的属性(例如,消息或自定义成员值),请在测试中将其捕获并进行断言。
在您的情况下,您似乎想要后者(断言该异常具有某个“ 4”值);使用ѭ5没错。
您应该“不使用try / catch”(被解释为“从不”)的概括是不正确的。
杰夫是对的。您的异常层次结构的组织是可疑的。但是,您似乎认识到这一点。 :)
, 听起来您的枚举被用作异常层次结构的替代方法?也许如果您有一个例外层次结构,则“ 6”会变得更有用吗?
, 如果要检查原始异常类型,则使用“ 3”方法是合适的。否则,如果您需要测试有关该异常的某些信息(并且不管消息内容是常见的enum
怪异测试),都可以进行try catch,但这有点陈旧。新的JUnit方法是使用MethodRule
。 API中的代码(ѭ10)专门用于测试消息,但是您可以轻松查看代码并改编该实现以检查失败ѭ8。
, 在特殊情况下,您要测试(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
}
}
这种模式将吞噬意外的异常并使测试失败。
编辑
更改它是因为我错过了显而易见的事情:我们可以使测试用例失败并捕获消息。所以现在:如果抛出带有预期错误代码的预期异常,则测试通过。如果由于出现意外错误而导致测试失败,则可以读取错误代码。
, 我在搜索如何处理异常时遇到了这个问题。
如@Yishai所述,期望异常的首选方式是使用JUnit规则和ExpectedException
。
当使用“ 14”时,如果在方法中的任何地方抛出异常,则测试方法将通过。
当您使用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()
。
附带说明:我不认为对异常消息/原因使用枚举不是一个好习惯。 (如果我错了,请纠正我。)
, 我犯了例外,因为我和您一样面临着同样的问题,斯特夫。
使用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() ;
}