Spring集成测试不会回滚

编程入门 行业动态 更新时间:2024-10-25 16:29:03
本文介绍了Spring集成测试不会回滚的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我使用Spring + Hibernate + H2。我在集成测试中执行数据库操作(通过调用服务类)。我希望Spring在每种测试方法之后回滚这些更改,但是我无法使其工作。起初我使用MySQL(与MyISAM,不支持交易),但在改为H2后,问题依然存在。我尝试了几个DataSource定义(在阅读之后,它必须是支持XA的),但似乎没有任何帮助。

我使用 code.google/p/generic-dao/ 为我的DAO-classes和@Transactional-annotations我的服务层(如果我删除它们,我得到以下错误:javax.persistence.TransactionRequiredException:没有事务正在进行中)。

我的测试类看起来像这样:

@ContextConfiguration(classpath:... spring.xml) @Transactional @TransactionConfiguration (transactionManager =transactionManager,defaultRollback = true) public class DemoServiceTest extends AbstractTestNGSpringContextTests { @Autowired DemoService demoService; @Test public void addTest() { int size = demoService.findAll()。size(); Test coach = new Test(); test.setName(Test); testService.save(test); Assert.assertEquals(size + 1,testService.findAll()。size()); $ / code $ / pre

这里是我的spring-configuration:

<! - < bean id =myDataSourceclass =org.apachemons.dbcp.BasicDataSource> - > <! - < property name =driverClassNamevalue =org.h2.Driver/> - > <! - < property name =urlvalue =jdbc:h2:〜/ test/> - > <! - < property name =usernamevalue =sa/> - > <! - < property name =passwordvalue =/> - > <! - < / bean> - > <! - < bean id =myDataSourceclass =com.mchange.v2.c3p0.ComboPooledDataSource> - > <! - < property name =driverClassvalue =org.h2.Driver/> - > <! - < property name =jdbcUrlvalue =jdbc:h2:〜/ test/> - > <! - < property name =uservalue =sa/> - > <! - < property name =passwordvalue =/> - > <! - < / bean> - > < bean id =myDataSourceclass =com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean> < property name =uniqueResourceNamevalue =test/> < property name =driverClassNamevalue =org.h2.Driver/> < property name =urlvalue =jdbc:h2:〜/ test/> < property name =uservalue =sa/> < property name =passwordvalue =/> < property name =maxPoolSizevalue =20/> < property name =reapTimeoutvalue =300/> < / bean> < bean id =demoDAOclass =... DemoDAOImpl/> < bean id =demoServiceclass =... DemoServiceImpl/> < bean id =entityManagerFactory class =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean> < property name =persistenceUnitNamevalue =test/> < property name =persistenceXmlLocationvalue =classpath:persistence.xml/> < property name =dataSourceref =myDataSource/> < property name =loadTimeWeaver> < bean class =org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver/> < / property> < property name =jpaVendorAdapterref =vendorAdapter/> < / bean> < bean id =vendorAdapter class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter> < property name =databasevalue =H2/> < property name =showSqlvalue =true/> < property name =generateDdlvalue =true/> < / bean> < bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager> < property name =entityManagerFactoryref =entityManagerFactory/> < / bean> < bean id =searchProcessorclass =com.googlecode.genericdao.search.jpa.JPASearchProcessor> < constructor-arg ref =metadataUtil/> < / bean> < bean id =metadataUtil class =com.googlecode.genericdao.search.jpa.hibernate.HibernateMetadataUtil factory-method =getInstanceForEntityManagerFactory> < constructor-arg ref =entityManagerFactory/> < / bean> < bean class =org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor/> < tx:annotation-driven />

这就是我的服务实现:

@Transactional public class TestServiceImpl implements TestService { private TestDAO< Test,Long>道; @Autowired public void setDao(TestDAO< Test,Long> dao){ this.dao = dao; } public void save(Test test){ dao.persist(test); dao.flush(); } public List< Test> findAll(){ return dao.findAll(); $ b $ public Test findByName(String name){ if(name == null) return null; return dao.searchUnique(new Search()。addFilterEqual(name,name)); $ b编辑:dao.persist() - 方法基本上从genericdao封装对以下方法的调用(em返回当前的EntityManager):

/ ** *< ; p为H. *使暂时实例持久化并将其添加到数据存储区。如果关联映射 *和cascade =persist,则 *操作会级联到关联的实例。如果实体已经存在,则抛出错误。 * *< p> *不保证立即为对象分配标识符 *。使用< code>持久< / code>数据存储区生成的ID可能不会被 *拉到刷新时间。 * / protected void _persist(Object ... entities){ for(Object entity:entities){ if(entity!= null) em ).persist(实体); $ / code $ / pre

一切正常,但更改仍保留在数据库中。任何想法?我认为你需要扩展AbstractTransactionalTestNGSpringContextTests而不是AbstractTestNGSpringContextTests。

解决方案

I'm using Spring + Hibernate + H2. I do database operations in my integration tests (by calling a service class). I want Spring to rollback the changes after each test method, but I can't get it to work. At first I used MySQL (with MyISAM, which doesn't support transaction), but after changing to H2 the problem remains. I tried several DataSource-definitions (after reading that it must be XA-aware), but nothing seems to help.

I use code.google/p/generic-dao/ for my DAO-classes and @Transactional-annotations in my service layer (if I remove them, I get the following error: javax.persistence.TransactionRequiredException: no transaction is in progress).

My test classes look like this:

@ContextConfiguration("classpath:...spring.xml") @Transactional @TransactionConfiguration(transactionManager="transactionManager", defaultRollback=true) public class DemoServiceTest extends AbstractTestNGSpringContextTests{ @Autowired private DemoService demoService; @Test public void addTest() { int size = demoService.findAll().size(); Test coach = new Test(); test.setName("Test"); testService.save(test); Assert.assertEquals(size+1,testService.findAll().size()); } }

Here's my spring-configuration:

<!-- <bean id="myDataSource" class="org.apachemons.dbcp.BasicDataSource"> --> <!-- <property name="driverClassName" value="org.h2.Driver" /> --> <!-- <property name="url" value="jdbc:h2:~/test" /> --> <!-- <property name="username" value="sa" /> --> <!-- <property name="password" value="" /> --> <!-- </bean> --> <!-- <bean id="myDataSource" class=" com.mchange.v2.c3p0.ComboPooledDataSource"> --> <!-- <property name="driverClass" value="org.h2.Driver" /> --> <!-- <property name="jdbcUrl" value="jdbc:h2:~/test" /> --> <!-- <property name="user" value="sa" /> --> <!-- <property name="password" value="" /> --> <!-- </bean> --> <bean id="myDataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"> <property name="uniqueResourceName" value="test" /> <property name="driverClassName" value="org.h2.Driver" /> <property name="url" value="jdbc:h2:~/test" /> <property name="user" value="sa" /> <property name="password" value="" /> <property name="maxPoolSize" value="20" /> <property name="reapTimeout" value="300" /> </bean> <bean id="demoDAO" class="...DemoDAOImpl" /> <bean id="demoService" class="...DemoServiceImpl" /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="test" /> <property name="persistenceXmlLocation" value="classpath:persistence.xml" /> <property name="dataSource" ref="myDataSource" /> <property name="loadTimeWeaver"> <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> </property> <property name="jpaVendorAdapter" ref="vendorAdapter" /> </bean> <bean id="vendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="H2" /> <property name="showSql" value="true" /> <property name="generateDdl" value="true" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="searchProcessor" class="com.googlecode.genericdao.search.jpa.JPASearchProcessor"> <constructor-arg ref="metadataUtil" /> </bean> <bean id="metadataUtil" class="com.googlecode.genericdao.search.jpa.hibernate.HibernateMetadataUtil" factory-method="getInstanceForEntityManagerFactory"> <constructor-arg ref="entityManagerFactory" /> </bean> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <tx:annotation-driven />

And that's my service implementation:

@Transactional public class TestServiceImpl implements TestService { private TestDAO<Test,Long> dao; @Autowired public void setDao(TestDAO<Test,Long> dao) { this.dao = dao; } public void save(Test test) { dao.persist(test); dao.flush(); } public List<Test> findAll() { return dao.findAll(); } public Test findByName(String name) { if (name == null) return null; return dao.searchUnique(new Search().addFilterEqual("name", name)); } }

EDIT: The dao.persist()-method basically encapsulates the call to the following method from genericdao (em returns the current EntityManager):

/** * <p> * Make a transient instance persistent and add it to the datastore. This * operation cascades to associated instances if the association is mapped * with cascade="persist". Throws an error if the entity already exists. * * <p> * Does not guarantee that the object will be assigned an identifier * immediately. With <code>persist</code> a datastore-generated id may not * be pulled until flush time. */ protected void _persist(Object... entities) { for (Object entity : entities) { if (entity != null) em().persist(entity); } }

Everything works fine, but the changes remain in the database. Any ideas?

解决方案

I think you need to extend from AbstractTransactionalTestNGSpringContextTests instead of AbstractTestNGSpringContextTests.

更多推荐

Spring集成测试不会回滚

本文发布于:2023-11-07 00:44:23,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:测试   Spring

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!