开发者

Spring @transactional does not start a transaction while testing with JUnit4

开发者 https://www.devze.com 2023-01-09 08:52 出处:网络
I have following configuration. <beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"

I have following configuration.

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

<bean id="dataSource" class="org.springframework.jdbc.datasource.IsolationLevelDataSourceAdapter">
    <property name="targetDataSource">
        <bean class="com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource">
            <property name="user" value="user"/>
            <property name="password" value="password"/>
            <property name="serverName" value="someserver"/>
            <property name="databaseName" value="someDBName"/>
            <property name="portNumber" value="somePortNumber"/>
        </bean>
    </property>
</bean>

<!-- this is bean is only used for data extraction module only -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
        </props>
    </property>
</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" lazy-init="true">
    <property开发者_开发问答 name="persistenceXmlLocation" value="classpath:persistence.xml" />
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
    </property>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>                
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>                
        </props>
    </property>
</bean>

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

<!--
    Instruct Spring to perform declarative transaction management automatically
    on annotated classes.  transaction-manager="transactionManager"
-->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

Then, when I ran tests that had an insert statement, they produced error messages as such:

javax.persistence.TransactionRequiredException: Executing an update/delete query
    at org.hibernate.ejb.QueryImpl.executeUpdate(QueryImpl.java:47)

After much deliberation, I tried this:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:services.xml" })
@Transactional(propagation = Propagation.REQUIRED)
@TransactionConfiguration(defaultRollback = true)
@TestExecutionListeners(value = { DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
public class SimpleUnitTest {

    @Test
    public void simpleTest() throws Exception {
        System.out.println(entityManager.getTransaction().isActive());
        assertTrue(entityManager.getTransaction().isActive());
   }
}

And it failed. entityManager.getTransaction().isActive() was in fact false.

Why wouldn't Transactional test does not begin a transaction?


You need to either add

@TestExecutionListeners(TransactionalTestExecutionListener.class)

or extend from

AbstractTransactionalJUnit4SpringContextTests

to get transactional behavior. (remember, your test class is not a bean, so regular transaction configuration does not apply)


The TransactionalTestExecutionListener is enabled by default, if you use SpringJUnit4ClassRunner.

You need to make sure you include the transaction management configuration in your Test context config:

@ContextConfiguration(locations = { "classpath:services.xml" })

So you can check it out by injecting the TM bean:

@Autowired
private PlatformTransactionManager transactionManager;

If the dependency is not resolved, then the transaction config isnot properly located.

During debugging your test, check for the TransactionInterceptor in your stacktrace.


Because you got two answers related to the configuration, I suppose the problem is not the configuration, but rather the problem how you check whether the transaction is active, and namely how you get that EntityManager instance.

A possible problem could be: EntityManagerFactory.createEntityManager() method is used instead of getting an injected EntityManager.

0

精彩评论

暂无评论...
验证码 换一张
取 消