Тест Junit не откатывает транзакцию на sqlserver

Я создал интеграционный тест службы, которая не откатывает транзакцию после завершения. Я знаю это, глядя на базу данных и из моей ошибки, которую я получаю, когда запускаю тест во второй раз. Я гуглю эту проблему все утро и чувствую, что все настроил правильно. Это приложение hibernate/jpa, записывающее в SQLServer 2008. Я не уверен, где еще искать. Фрагмент ниже.

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
        DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class,
        TransactionalTestExecutionListener.class })
@TransactionConfiguration(defaultRollback=true)
@Transactional // extend transactional boundary to test class so that automatic rollback works properly
@ContextConfiguration(locations = {
        "file:./src/main/resources/AghostMobile.Service-business.service-context.xml",
        "file:./src/main/resources/AghostMobile.Service-service-context.xml",
        "file:./src/main/resources/AghostMobile.Service-dao-context.xml"})
public class ColorSchemeMigrationServiceIntTest {

    /**
     * The service being tested, injected by Spring
     *
     */
    @Autowired
    ColorSchemeMigrationService service;

    /**
     * The helper services, injected by Spring.
     *
     */
    @Autowired
    protected WebsitecolorpaletteuserdefinedService userPaletteService;
    @Test
    public void testSaveColorPalette() {
        Integer mobileWebsiteId = Integer.valueOf(386);
        Integer custId = Integer.valueOf(15);
        Integer siteId = Integer.valueOf(2);
        String user = "Test";

        Websitecolorpaletteuserdefined palette = service.translateColorScheme(mobileWebsiteId, custId, siteId, user);

        service.saveColorPalette(palette);

        Websitecolorpaletteuserdefined response = userPaletteService.findWebsitecolorpaletteuserdefinedByCustIdAndSiteId(custId, siteId);

        assertNotNull("User palette not found.", response);
        assertEquals("CustId is not the expected value.", custId, response.getCustId());
        assertEquals("SiteId is not the expected value.", siteId, response.getSiteId());
    }

В настоящее время у меня определены следующие компоненты:

<!-- ******************************************************************** -->
<!-- Setup the transaction manager -->
<!-- ******************************************************************** -->
    <!-- Using Atomikos Transaction Manager -->
    <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init"
        destroy-method="close">
        <property name="forceShutdown" value="true" />
        <property name="startupTransactionService" value="true" />
        <property name="transactionTimeout" value="60" />
    </bean>

    <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" />
    <!-- Configure the Spring framework to use JTA transactions from Atomikos -->
    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="atomikosTransactionManager" />
        <property name="userTransaction" ref="atomikosUserTransaction" />
        <property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" />
    </bean>
<!-- ******************************************************************** -->
<!-- Setup a data source -->
<!-- ******************************************************************** -->
<!-- Using Apache DBCP Data Sources -->
<bean name="hostDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" >
    <property name="driverClassName" value="${My_JDTs_to_AgHost_Host_scheme.connection.driver_class}" />
    <property name="username" value="${My_JDTs_to_AgHost_Host_scheme.connection.username}" />
    <property name="password" value="${My_JDTs_to_AgHost_Host_scheme.connection.password}" />
    <property name="url" value="${My_JDTs_to_AgHost_Host_scheme.connection.url}" />
    <property name="maxIdle" value="${My_JDTs_to_AgHost_Host_scheme.minPoolSize}" />
    <property name="maxActive" value="${My_JDTs_to_AgHost_Host_scheme.maxPoolSize}" />
</bean>

<!-- ******************************************************************** -->
<!-- Setup each persistence unit -->
<!-- ******************************************************************** -->
            <!-- Configure a JPA vendor adapter -->
            <bean id="My_JDTs_to_AgHost_Host_schemeJPAVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="${My_JDTs_to_AgHost_Host_scheme.show_sql}" />
                <property name="generateDdl" value="${My_JDTs_to_AgHost_Host_scheme.generateDdl}" />
                <property name="databasePlatform" value="${My_JDTs_to_AgHost_Host_scheme.dialect}" />
            </bean>
            <!-- EntityManager Factory that brings together the persistence unit, datasource, and JPA Vendor -->
            <bean id="My_JDTs_to_AgHost_Host_scheme" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                <property name="dataSource" ref="hostDataSource" />
                <property name="persistenceUnitName" value="My_JDTs_to_AgHost_Host_scheme" />
                <property name="jpaVendorAdapter" ref="My_JDTs_to_AgHost_Host_schemeJPAVendorAdapter" />
                    <property name="jpaPropertyMap">
                        <map>
                                    <entry key="hibernate.transaction.manager_lookup_class" value="com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup" />
                                    <!-- <entry key="hibernate.transaction.factory_class" value="org.hibernate.transaction.JTATransactionFactory" /> -->
                                    <entry key="hibernate.connection.release_mode" value="on_close" />
                        </map>
                    </property>
            </bean>

Это позволяет мне обновлять мои данные, но не откатывает мою транзакцию. Итак, я использую менеджер транзакций, org.springframework.jdbc.datasource.DataSourceTransactionManager. Я заменил три компонента в блоке «Настройка диспетчера транзакций» на:

    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="hostDataSource" />
    </bean>

Это оставило меня с ошибками тестов с IllegalStateException: этому методу нужна транзакция для вызывающего потока, а ее не существует. В исключении также указано:

Possible causes: either you didn't start a transaction,
it rolledback due to timeout, or it was committed already.
ACTIONS: You can try one of the following: 
1. Make sure you started a transaction for the thread.
2. Make sure you didn't terminate it yet.
3. Increase the transaction timeout to avoid automatic rollback of long transactions;
   check [http://www.atomikos.com/Documentation/JtaProperties][1] for how to do this.

Я признаю, что еще не читал этот документ и сделаю это после публикации этих обновлений. Я также нашел эту ветку, которая выглядела многообещающе: , другое свойство hibernate.transaction.manager_lookup_class. Вы можете видеть, что это закомментировано в bean-компоненте My_JDTs_to_AgHost_Host_scheme. Это с треском провалилось. Но, возможно, я не использовал его должным образом.

Я также нашел эту тему: Проверка интеграции Spring/JTA/JPA DAO не откат?. Это выглядит довольно многообещающе, но опять же я не уверен, как использовать то, что он говорит мне.


person Bill Turner    schedule 03.10.2012    source источник
comment
Вы пытались использовать @Transactional для каждого метода тестирования вместо всего класса? Ожидаете ли вы, что данные будут поддерживаться между тестовыми примерами, но будут откатываться после завершения класса? Или вы ожидаете отката после каждого метода?   -  person Jesse Webb    schedule 03.10.2012
comment
@JesseWebb размещение аннотации @Trasactional на уровне тестового класса является стандартной практикой отката транзакций после каждого теста.   -  person John B    schedule 03.10.2012
comment
@JesseWebb - я ожидаю, что тесты будут откатываться после каждого теста. У меня такое же понимание, как у JohnB   -  person Bill Turner    schedule 03.10.2012
comment
@JohnB - Спасибо за разъяснение, я думал, что он ведет себя по-разному применительно к классу по сравнению с каждым методом. Похоже, что ОП попал в нужное место для того, чего он пытается достичь.   -  person Jesse Webb    schedule 03.10.2012
comment
Я обновил исследования до сих пор. До сих пор нет ответа.   -  person Bill Turner    schedule 05.10.2012


Ответы (2)


Ответ оказался здесь: Интеграция Spring/JTA/JPA DAO тест не откатывается?. Я изменил источник данных на следующий.

<bean name="hostDataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean" destroy-method="close" >
    <property name="driverClassName" value="${My_JDTs_to_AgHost_Host_scheme.connection.driver_class}" />
    <property name="user" value="${My_JDTs_to_AgHost_Host_scheme.connection.username}" />
    <property name="password" value="${My_JDTs_to_AgHost_Host_scheme.connection.password}" />
    <property name="url" value="${My_JDTs_to_AgHost_Host_scheme.connection.url}" />

    <property name="maxPoolSize" value="20" />
    <property name="reapTimeout" value="300" />
    <property name="uniqueResourceName" value="myappDatabase" />
</bean>
person Bill Turner    schedule 19.10.2012

У вас есть bean-компонент DataSourceTransactionManager в загруженном контексте?

пример DataSourceTransactionManager

См. раздел 9.3.

person John B    schedule 03.10.2012
comment
Кажется, нет. Буду гуглить как это сделать. Если есть ссылки, буду признателен. :-) - person Bill Turner; 03.10.2012