2012-12-21 29 views
0

获得 “无交易正在进行中” 我使用Spring 3.1.1.RELEASE,JUnit的4.8.1,休眠4.1.0.Final,和休眠,JPA-2.0-API。我试图运行这个JUnit测试...在Spring JUnit测试

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ "classpath:test-context.xml" }) 
public class UserDaoImplTest extends AbstractTransactionalJUnit4SpringContextTests 
{ 
    … 
    @Test 
    public final void testSave() 
    { 
     final User user = new User(); 
     user.setFirstName(testProps.getProperty("test.user.first.name")); 
     user.setLastName(testProps.getProperty("test.user.last.name")); 
     user.setMiddleName(testProps.getProperty("test.user.middle.name")); 
     user.setPassword(testProps.getProperty("test.user.password")); 
     final Role role = rolesDao.findRoleByName(testProps.getProperty("test.role.teacher.name")); 
     user.setRole(role); 
     user.setUrl(testProps.getProperty("test.user.url")); 
     user.setUserName(testProps.getProperty("test.user.username")); 
     final User savedUser = userDao.save(user); 
     Assert.assertNotNull(savedUser.getId()); 
     final User foundUser = userDao.findById(savedUser.getId()); 
     Assert.assertEquals(savedUser, foundUser); 
    } // testSave 

,并在“userDao.save”行,我得到了fullowing例外。我认为“AbstractTransactionalJUnit4SpringContextTests”保证每个测试都是事务性的?我能做些什么来解决这个问题?

javax.persistence.TransactionRequiredException: no transaction is in progress 
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:971) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365) 
    at $Proxy30.flush(Unknown Source) 
    at org.mainco.subco.user.repo.UserDaoImpl.save(UserDaoImpl.java:118) 
    at org.mainco.subco.user.test.repo.UserDaoImplTest.testSave(UserDaoImplTest.java:226) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31) 
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83) 
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) 
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174) 
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

下面是测试context.xml文件的内容...

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:tx="http://www.springframework.org/schema/tx" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.1.xsd 
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-3.1.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> 

    <context:component-scan base-package="org.mainco.subco" /> 

    <!-- Define hashing properties --> 
    <bean id="localPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> 
     <property name="location"> 
      <value>classpath:encryption.properties</value> 
     </property> 
    </bean> 

    <!-- Define test properties --> 
    <util:properties id="applicationProperties" location="classpath:test.properties" /> 

    <bean id="dataSource" 
     class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="org.h2.Driver" /> 
     <property name="url" value="jdbc:h2:~/ebook-test" /> 
     <property name="username" value="" /> 
     <property name="password" value="" /> 
    </bean> 

    <bean id="entityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="jpaVendorAdapter"> 
      <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> 
     </property> 
     <property name="persistenceXmlLocation" value="classpath*:META-INF/test-persistence.xml" /> 
     <property name="persistenceUnitName" value="usersTestingDatabase" /> 
     <property name="dataSource" ref="dataSource" /> 
    </bean> 

    <bean id="sharedEntityManager" 
     class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    </bean> 

    <tx:annotation-driven transaction-manager="transactionManager" /> 

    <bean id="bcProvider" class="${hash.provider.class}" /> 

    <bean id="jasyptStringDigester" class="org.jasypt.digest.StandardStringDigester"> 
     <property name="algorithm"> 
      <value>${digest.algorithm}</value> 
     </property> 
     <property name="provider"> 
      <ref bean="bcProvider" /> 
     </property> 
     <property name="saltGenerator"> 
      <ref bean="saltGenerator" /> 
     </property> 
     <property name="saltSizeBytes" value="${salt.bytes.length}" /> 
    </bean> 

    <bean id="saltGenerator" class="${salt.generator.class}" /> 

    <!-- This Spring Security-friendly PasswordEncoder implementation will --> 
    <!-- wrap the StringDigester instance so that it can be used from --> 
    <!-- the security framework. --> 
    <bean id="passwordEncoder" 
     class="org.jasypt.springsecurity3.authentication.encoding.PasswordEncoder"> 
     <property name="stringDigester"> 
      <ref bean="jasyptStringDigester" /> 
     </property> 
    </bean> 

    <jdbc:embedded-database id="embedded" type="H2" /> 
    <jdbc:initialize-database data-source="dataSource"> 
     <jdbc:script location="classpath:db-test-data.sql" /> 
    </jdbc:initialize-database> 

</beans> 
+0

有你定义的测试context.xml中 – NimChimpsky

+0

另外一个事务管理器,因为你大部分的测试代码使用注解,你可以只添加@Transactional给你测试。默认是回滚。 –

+0

@NimChimpsky - 我包含了我的test-context.xml文件的内容。请注意,我确实定义了一个TransactionManager,但也许它与某种方式有关。 – Dave

回答

1

毕竟那,问题是,userDAO的和rolesDao对象执行不同的实体管理器,一个来自德上下文中自动连接,和其他在测试中实例化。

0

一些与你的配置接缝是错误的:你有两个数据源!定义 一个explicite:

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="org.h2.Driver" /> 
    <property name="url" value="jdbc:h2:~/ebook-test" /> 
    <property name="username" value="" /> 
    <property name="password" value="" /> 
</bean> 

和一个implicite定义:

<jdbc:embedded-database id="embedded" type="H2" /> 
<jdbc:initialize-database data-source="dataSource"> 
    <jdbc:script location="classpath:db-test-data.sql" /> 
</jdbc:initialize-database> 

当我做测试,像你这样,我的设置是这样的(和它的作品):

<jdbc:embedded-database id="dataSource" type="H2" > 
    <jdbc:script location="classpath:ddlAdditional_h2.sql" />  
</jdbc:embedded-database> 

<bean 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    id="entityManagerFactory"> 
    <property name="persistenceUnitName" value="testH2DbPersistenceUnit" /> 
    <property name="dataSource" ref="dataSource" /> 

    <!-- this is important to connect JPA and JdbcTemplate transaction control --> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
      <property name="showSql" value="false" /> 
     </bean> 
    </property> 
</bean> 

<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager" /> 

顺便说一句:将@Transactional添加到单个测试方法或您的测试cl屁股(这就像将其添加到所有测试方法)。那么你不需要再延伸AbstractTransactionalJUnit4SpringContextTests了。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({ "classpath:test-context.xml" }) 
@Transactional 
public class UserDaoImplTest { 

    @Test 
    public test() {...} 
} 

然后将试验方法将在将在结束时rollbacked事务中运行。

+0

我删除了“扩展AbstractTransactionalJUnit4SpringContextTests”并添加了@Transactional注解,但在重新运行测试时仍然出现相同的错误。 – Dave

+0

我已经添加了一些关于配置的评论,我希望这可以帮助你。 (顺便说一句:我的设置使用内存分贝测试) – Ralph

+0

嗨,我也使用了内存分贝,所以你的设置可以帮助我。但我有一个问题 - 我使用SQL脚本插入测试数据,但我使用“”属性定义自动创建表结构在我的test-persistence.xml文件中。你如何生成你的内存表结构? – Dave