我正在为我的DAO编写一些测试,因为很多测试都使用了保存到我的数据库的测试对象,所以我创建了一个带有注释@Before的setup()和teardown()方法。 @After分别避免冗余代码,但其中一个测试,实际上是一个不需要测试对象的测试,在DAO中调用一个包含调用getCurrentSession()。clear()的方法(这是一个使用ScrollableResults的方法)要批量从db获取数据,并避免内存填满,每50行调用flush()和clear())。这会产生一个问题,因为clear()实际上会从会话中删除在setup()中创建的测试对象,因此当调用teardown()时会出现错误:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [nl.ru.cmbi.pdbeter.core.model.domain.PDBEntry#395]
有没有办法告诉JUnit在这个测试中不使用setup()和teardown(),或者最好将所有不需要setup()和teardown()的测试放在一个新的测试类?
答案 0 :(得分:6)
首先,是的,在单独的测试中隔离不需要@Before
或@After
行为的测试很有意义。
其次,您可能需要查看在每次测试结束时自动回滚的Spring Framework's support for running unit tests within a database transaction,这样您就不必担心某些影响外部资源状态的测试或者询问有关每个订单中正在运行哪些测试的问题等。将其与内存数据库(如HSQL)结合使用,您甚至不必担心在某个地方运行数据库,使您的构建更加便携。
答案 1 :(得分:2)
JUnit将为每个测试运行所有使用@Before
和@After
注释的方法,因此您需要将测试分成两个类。
答案 2 :(得分:0)
定义您自己的BlockJUnit4ClassRunner:
public class WithoutBeforeAfter extends BlockJUnit4ClassRunner {
public WithoutBeforeAfter(Class<?> klass) throws InitializationError {
super(klass);
}
@Override
protected Statement withBefores(FrameworkMethod method, Object target, Statement statement) {
if(method.getName().equals("methodNameIgnore@Before")){
return statement;
}else{
return super.withBefores(method, target, statement);
}
}
@Override
protected Statement withAfters(FrameworkMethod method, Object target, Statement statement) {
if(method.getName().equals("methodNameIgnore@After")){
return statement;
}else{
return super.withAfters(method, target, statement);
}
}
}
然后在测试用例中使用它:
@RunWith(value=WithoutBeforeAfter.class)
至少它在JUnit 4.8中可用。