I have a small app that reads a few databases, and writes a small table in one database. I have a @Service-annotated class with a @Transactional method. That method calls a method in a DAO class (which is not @Repository-annotated) which first deletes some rows from a table and then inserts rows to the same table.
This gets deployed to WebLogic. Under normal operation this app is working perfectly fine.
I tried an experiment of deliberately mucking the SQL for the "insert", and deployed this to my local box, and then executed the JMX operation that executes this service operation. After it failed I checked the database, and I confirmed that the table was intact, so it correctly rolled back the "delete" when the "insert" failed.
My problem is that my integration test that tries to simulate a similar scenario is NOT behaving transactionally. I mocked the JdbcTemplate so it performed the delete, but forced it to throw a DataAccessException on the insert. Afterwards, I checked the database, and the rows were gone, so it didn't rollback the delete as I hoped.
I'm using the Atomikos transaction manager for my tests. The following is an excerpt from the context I'm using in test to define the "catalogTransactionManager", which is what is referenced in the rest of the context.
It probably doesn't matter, but here's my test method (with some things obfuscated):Code:<!-- 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>
What might I be missing?Code:@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); }


Reply With Quote