在大多数JUnit测试中抛出异常是否违反最佳做法?

时间:2010-03-22 23:36:21

标签: java unit-testing junit

我的几乎所有JUnit测试都使用以下签名编写:

public void testSomething() throws Exception

我的理由是我可以专注于我正在测试的内容,而不是JUnit似乎免费提供给我的异常处理。但这样做我错过了什么吗?这是违反最佳做法的吗?我可以通过在测试中明确捕获特定异常然后失败()来获取任何东西吗?

4 个答案:

答案 0 :(得分:53)

一般情况下,如果您正在测试一个不希望发生异常的情况,那么我只是让测试方法抛出Exception,因为它可以很好地区分失败测试用例(它们没有通过你的一个断言)和错误测试用例(它们会导致意外的异常)。 JUnit TestRunners将捕获抛出的异常,无论如何,如果抛出异常,您不必担心整个测试套件挽救。

另一方面,如果您正在编写一个应该触发异常的测试,那么您要么使用JUnit 4注释的@Test(expected=IllegalArgumentException.class)变体,要么使用更常见的JUnit 3习惯用法:

try {
  target.someMethodToTest();
  fail("Should have gotten an exception");
} catch (IllegalStateException ise) {
  //expected, it's all good
}

答案 1 :(得分:11)

不要抓住并失败 - 你将丢失有价值的信息。让所有例外都飞出来。这意味着您需要为每个已检查的异常添加可以抛出的签名。但是,我建议你不要采取懒惰的方式,盲目地使用throws Exception作为习惯。这使您甚至不必思考关于API如何在异常方面的真实行为。

答案 2 :(得分:3)

主要好处包括当您测试某些需要抛出异常的场景时(例如错误处理)

你可以在JUnit4中使用类似:@Test(expected = ArithmeticException.class)但是有些人发现比明确的try {} catch(Exception e)块更难阅读/更少意图揭示,如果你想要检查状态(比如一些模拟对象,或者查看异常是在正确的位置抛出,还是记录,等等)

答案 3 :(得分:3)

如果抛出异常,并且您没有预料到,则测试应该失败。

如果它是未经检查的异常,我允许抛出异常并使JUnit无法通过测试。

如果它是一个已检查的异常,您可以选择:将该异常添加到方法签名的throws子句中,或者在方法内捕获它。编译器将强制您选择,因为如果没有这些选择,您将无法运行代码。

最近我倾向于不在我的测试中捕获异常。如果它应该抛出一个异常,我用注释标记它。如果它抛出一个未经检查的异常,我让JUnit为我测试失败了。如果它是一个已检查的异常,我将throws子句添加到方法签名中,并让JUnit为我测试失败。