У меня есть небольшое приложение Spring, которое читает несколько баз данных и пишет небольшую таблицу в одной базе данных. У меня есть класс @ Service-annotated с методом @Transactional. Этот метод вызывает метод в классе DAO (который не является @ Repository-annotated), который сначала удаляет некоторые строки из таблицы, а затем вставляет строки в одну и ту же таблицу.Как я могу заставить свой Spring transactionmanager в моем интеграционном тесте действительно быть транзакционным?
Это развертывается в WebLogic. При нормальной работе это приложение работает отлично.
Я попробовал эксперимент по умышленному удалению SQL для «вставки» и развернул его в своем локальном поле, а затем выполнил операцию JMX, которая выполняет эту служебную операцию. После того, как он потерпел неудачу (ожидается), я проверил базу данных, и я подтвердил, что таблица была неповрежденной, поэтому она корректно откатывала «удалить», когда «вставка» не удалась.
Моя проблема заключается в том, что мой интеграционный тест, который пытается имитировать подобный сценарий, НЕ ведет себя транзакционно. Я издевался над JdbcTemplate, поэтому он выполнил удаление, но заставил его бросить исключение DataAccessException. Впоследствии я проверил базу данных, и строки исчезли, поэтому она не отменила удаление, как я надеялся.
Я включил отладку в пакете Spring JTA, и я увидел отладочную распечатку сообщения, в котором говорится, что он откатывает транзакцию.
Я использую диспетчер транзакций Atomikos для своих тестов. Ниже приведен фрагмент из контекста, который я использую в тесте, чтобы определить «catalogTransactionManager», на что ссылается в остальной части контекста.
<!-- Construct Atomikos UserTransactionManager, needed to configure Spring -->
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<!-- when close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown">
<value>true</value>
</property>
</bean>
<!-- Also use Atomikos UserTransactionImp, needed to configure Spring -->
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">
<property name="transactionTimeout">
<value>300</value>
</property>
</bean>
<!-- Configure the Spring framework to use JTA transactions from Atomikos -->
<bean id="catalogTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<ref bean="atomikosTransactionManager" />
</property>
<property name="userTransaction">
<ref bean="atomikosUserTransaction" />
</property>
</bean>
Это, вероятно, не имеет значения, но вот мой метод испытания (с некоторыми вещами затемненный):
@Test
public void testInsertFailsAfterDelete() {
List<ErrorMessageInfo> commonErrorMessagesBefore =
myService.
getMyDAO().getCommonErrorMessages(MyService.CHANNEL_NAME);
JdbcTemplate template = mock(JdbcTemplate.class);
myService.getMyDAO().setJdbcTemplate(template);
when(template.update(eq(MyDAO.SQL_DELETE_CHANNEL), any())).
thenReturn(getOrigTemplate().update(MyDAO.SQL_DELETE_CHANNEL, MyService.CHANNEL_NAME));
DataAccessException exception = new DataAccessException("insert failed") {};
when(template.update(eq(MyDAO.SQL_INSERT_ERROR_TO_CHANNEL), anyString(), anyString(), anyInt(), any(), anyInt())).
thenThrow(exception);
try {
myService.updateCommonErrorMessages();
fail();
}
catch (Exception ex) {
assertThat(ex).isEqualTo(exception);
}
finally {
restoreTemplate();
}
List<ErrorMessageInfo> commonErrorMessagesAfter =
myService.
getMyDAO().getCommonErrorMessages(MyService.CHANNEL_NAME);
assertThat(commonErrorMessagesBefore).isEqualTo(commonErrorMessagesAfter);
}
Обратите внимание, что, хотя, когда я раскрываю к WebLogic, я определяю обычный транзакционный источник данных объединения пула соединений, но в моем интеграционном тесте источник данных использует «org.springframework.jdbc.datasource.DriverManager DataSource».
Что я могу пропустить?
Это просто потому, что бесплатный менеджер транзакций Atomikos не является транзакционным? Что я могу пропустить?
как вы получаете mySerive - это AutoWired? – gkamal
Да, myService автоуведомлен. –