在JUnit中使用Springtesting服务时如何回滚数据库事务?
我没有问题testing我的DAO和服务,但是当我testingINSERT
或UPDATE
我想回滚事务,而不是影响我的数据库。
我在我的服务中使用@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
在课前使用以下注释:
@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方法。