我知道如何配置Spring / JUnit以在每个测试用例后回滚。 我所追求的是一种为所有测试用例启动和回滚一个事务的方法。
我正在使用@BeforeClass为几个测试用例准备我的HSQL数据库。然后我想在@AfterClass中的所有测试用例结束后回滚更改。
实现此回滚的最佳方法是什么?
这是我的代码示例:
@BeforeClass
public static void setupDB(){
ApplicationContext context = new ClassPathXmlApplicationContext(
"classpath:/spring/applicationContext-services-test.xml");
//- get beans and insert some records to the DB
...
}
@AfterClass
public static void cleanUp(){
??? what should go here?
}
有关在AfterClass中进行回滚的最佳方法的任何想法吗?
感谢所有..
答案 0 :(得分:5)
如果您在每次测试后回滚并使用Spring是可以接受的,那么我项目中的以下代码段可能会对您有所帮助:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/net/sukharevd/shopzilla/model/application-context-dao.xml" })
@TestExecutionListeners(DependencyInjectionTestExecutionListener.class)
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
@Transactional
public class HibernateCategoryDaoTest extends AbstractTransactionalJUnit4SpringContextTests {
答案 1 :(得分:3)
您可能不希望在课后进行回滚,但是在每次测试之后。测试不保证每次都以相同的顺序运行,因此您可能会得到不同的结果。单元测试应该是隔离的。
您可以使用spring test runner来注释您的类和回滚事务
@RunWith(SpringJUnit4ClassRunner.class)
@TransactionConfiguration(defaultRollback=true)
public static class YourTestClass {
@Test
@Transactional
public void aTest() {
// do some db stuff that will get rolled back at the end of the test
}
}
一般情况下,您还应该尽量避免在单元测试中遇到真正的数据库。击中数据库的测试通常是集成级别测试(或甚至更粗糙的测试,如验收测试)。 DBUnit http://www.dbunit.org/框架用于存储单元测试的数据库,因此您不需要使用真实的数据库。
答案 2 :(得分:2)
我设法使用Spring / JUnit(不使用DBUnit)解决了这个问题。
简而言之,解决方案是在@BeforeClass中调用transactionManager.getTransaction(def).setRollbackOnly();
。
首先让我解释一下我的目的。 我的主要动机是这个流程:
1.开始交易
2.插入负载测试数据
3.在相同的测试数据上运行几个测试用例
4.回滚测试数据。
由于我在@BeforeClass中构建负载测试数据,因此我希望在@AfterClass中回滚。这似乎是不必要的,因为我可以简单地指示事务只在我的@BeforeClass中回滚!
所以我就是这样做的:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:/spring/applicationContext-services-test.xml")
@TestExecutionListeners(inheritListeners = false, listeners = { SpecialDependencyInjectionTestExcecutionListener.class })
@TransactionConfiguration(defaultRollback = true)
@Transactional
public class loadTest {
...
private static HibernateTransactionManager transactionManager;
...
@BeforeClass
public static void setupDB() {
//- set the transaction to rollback only. We have to get a new transaction for that.
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionManager.getTransaction(def).setRollbackOnly();
...
//- start loading the data using the injected services.
...
}
这有助于在课程结束时回滚。
附: SpecialDependencyInjectionTestExcecutionListener
是DependencyInjectionTestExecutionListener
的扩展,我曾用它覆盖beforeTestClass,强制在调用@BeforeClass之前加载application.context。感谢Dmitriy强调这个倾听者,这是解决我心中想到的另一个问题的暗示。
感谢所有帮助突出显示的建议和建议,这些建议共同促成了我的解决方案。
Dhafir
答案 3 :(得分:0)
让我们假装你没有使用Spring。 (因为使用Spring,其他答案在这里更好。)那么你将有三个选择:
答案 4 :(得分:0)
查看How to load DBUnit test data once per case with Spring Test的已接受答案。所有测试完成后,您可以使用此技术执行数据库清理。