Results 1 to 3 of 3

Thread: How to make my integration test transactional?

  1. #1
    Join Date
    Jan 2006
    Location
    Seattle, Washington
    Posts
    467

    Default How to make my integration test transactional?

    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.
    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>
    It probably doesn't matter, but here's my test method (with some things obfuscated):
    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);
    }
    What might I be missing?

  2. #2
    Join Date
    Jan 2006
    Location
    Seattle, Washington
    Posts
    467

    Default

    Note that although when I deploy to WebLogic, I define a normal connection-pooling transactional datasource, but in my integration test, the datasource uses a "org.springframework.jdbc.datasource.DriverManager DataSource". Could that be part of the problem? Is there an alternative?

  3. #3
    Join Date
    Jan 2006
    Location
    Seattle, Washington
    Posts
    467

    Default

    I tried setting debug on "org.springframework.transaction" and I saw it print "JtaTransactionManager - Initiating transaction rollback", but when I inspected the database, I saw that it committed the delete.

    Is this happening because the free Atomikos transaction manager isn't really transactional?

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •