Я создал интеграционный тест службы, которая не откатывает транзакцию после завершения. Я знаю это, глядя на базу данных и из моей ошибки, которую я получаю, когда запускаю тест во второй раз. Я гуглю эту проблему все утро и чувствую, что все настроил правильно. Это приложение 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 не откат?. Это выглядит довольно многообещающе, но опять же я не уверен, как использовать то, что он говорит мне.
@Transactional
для каждого метода тестирования вместо всего класса? Ожидаете ли вы, что данные будут поддерживаться между тестовыми примерами, но будут откатываться после завершения класса? Или вы ожидаете отката после каждого метода? - person Jesse Webb   schedule 03.10.2012@Trasactional
на уровне тестового класса является стандартной практикой отката транзакций после каждого теста. - person John B   schedule 03.10.2012