我写单元测试我们的主要产品,并有一个担忧:如何区分语义对损坏的单元测试
- 测试失败,因为他们测试了错误(错误被发现和非回归测试它的实例)
- 测试失败,因为测试的另一个意想不到的部分失败(因为测试是错误的或未知的bug出现)
这是第一个,我们对JUnit的断言框架当然,但是我们对第二个有什么?例如:我的单元测试正在测试c()不会抛出MyException,而是执行c()我需要先执行一个()然后b(),它们都可以抛出MyException(),所以我会写:
@Test
public void testC() {
a();
Object forC = b();
try {
c(forC);
} catch (MyException e) {
Assert.fail("....");
}
}
但是然后我需要处理可以由a或b抛出的MyException,并且还处理了forC不应该为null的事实。做这个的最好方式是什么?
- Catch MyException抛出a或b和Assert.fail,但a和b没有通过这个测试测试,所以对我来说,他们不应该被标记为失败时测试失败。也许他们以后失败,因为在这个时候我们应该做b(); a()不是a(); b();.
- 让testC抛出MyException,这样测试将失败并显示“MyException”,但这是误导,因为MyException不会告诉测试写错了。所有的测试都会失败,每个都有自己的异常。在这种情况下,如果forC为空(也没有语义),我还需要抛出类似NullPointerException的内容。
- 将a和b抛出的异常捕获并包装成异常,告诉测试可能是错误的,就像TestCorruptedException。但是我不能在jUnit中找到这样的异常,所以它们不会被jUnit识别(这对我来说没问题)。另外我需要从我所有的单元测试中知道这个异常,当然这些单元测试分为多个模块,项目等等。所以这是可行的,但是增加了依赖性。
你会怎样解决这个问题?如上所述,我可能会参加第二场比赛,但我对此并不满意。
正确的,我的问题是确实是c是紧密相连的一个()因为它们的真名是startTransaction()和commit(),所以它们具有公共结构和锁。你的回答告诉我,我正在进行集成测试,所以我注定要失败,只能祈求a和b是正确的。它太过努力让他们独立,但这对我来说是解决问题的方法。 – jolivier 2012-07-13 17:00:54
这就是像[Spring的注解驱动的事务管理](http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html#transaction- declarative-annotations)这样的声明式事务管理真正发光的地方。您的方法c()可以抛弃对startTransaction()和commit()的调用,让您可以自由地对其进行测试。 c()不会在意它是否在事务中,你会在调用方法中捕获任何异常。这里是一个[小型教程](http://www.javacodegeeks.com/2011/09/spring-declarative-transactions-example.html)感兴趣 – Brad 2012-07-13 20:36:34