在JUnit中使用Springtesting服务时如何回滚数据库事务?

我没有问题testing我的DAO和服务,但是当我testingINSERTUPDATE我想回滚事务,而不是影响我的数据库。

我在我的服务中使用@Transactional来pipe理事务。 我想知道,是否有可能知道一个事务是否可以正常工作,但是为了防止改变数据库而回滚它?

这是我的testing:

 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:/META-INF/spring.cfg.xml") @TransactionConfiguration(defaultRollback=true) public class MyServiceTest extends AbstractJUnit38SpringContextTests { @Autowired private MyService myService; @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Test public void testInsert(){ long id = myService.addPerson( "JUNIT" ); assertNotNull( id ); if( id < 1 ){ fail(); } } } 

问题是这个testing会失败,因为事务被回滚了,但插入是OK的! 如果我删除@TransactionConfiguration(defaultRollback=true)那么testing通过,但新的logging将被插入到数据库中。

 @Test @Transactional @Rollback(true) public void testInsert(){ long id = myService.addPerson( "JUNIT" ); assertNotNull(id); if( id < 1 ){ fail(); } } 

现在可以正确地testing通过,但回滚被忽略,并且logging被插入到数据库中。 我用@Transactional注释了myService中的方法addPerson() ,显然。 为什么回滚被忽略?

您需要将事务边界扩展到testing方法的边界。 你可以通过@Transactional注释你的testing方法(或整个testing类)

 @Test @Transactional public void testInsert(){ long id=myService.addPerson("JUNIT"); assertNotNull(id); if(id<1){ fail(); } } 

您也可以使用这种方法来确保数据在回滚之前被正确写入:

 @Autowired SessionFactory sf; @Test @Transactional public void testInsert(){ myService.addPerson("JUNIT"); sf.getCurrentSession().flush(); sf.getCurrentSession().doWork( ... check database state ... ); } 

查看

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

特别是第8.3.4节

Spring有一些testing类,将每个testing包装在一个事务中,所以数据库不会被改变。 你也可以改变这个function。

编辑 – 基于你的更多信息,你可能想看看

AbstractTransactionalJUnit38SpringContextTests at

http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/context/junit38/AbstractTransactionalJUnit38SpringContextTests.html

在课前使用以下注释:

 @TransactionConfiguration(transactionManager = "txManager",defaultRollback = true) @Transactional 

这里txManager是应用程序上下文的事务pipe理器。

这里txManager是一个来自application context的事务pipe理器的实例或bean id。

 <!-- Transaction Manager --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <tx:annotation-driven transaction-manager="txManager" /> 

setUp()方法中添加你的代码,这将在testing开始时执行,最后的代码应该放在最后执行的teatDown()方法中。 或者你也可以使用@Before@After注解代替它。

如果你的

 myService.addPerson("JUNIT"); 

方法被注释为@Transactional你会得到一些不同的种类或错误试图解决这个问题。 所以你最好只是testingDAO方法。