views:

72

answers:

2

I am doing unit testing and I expect that all data committed to the MySQL database will be rolled back... but this isn't the case. The data is being committed, even though my log was showing that the rollback was happening. I've been wrestling with this for a couple days so my setup has changed quite a bit, here's my current setup.

LoginDAOTest.java:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:web/WEB-INF/applicationContext-test.xml", "file:web/WEB-INF/dispatcher-servlet-test.xml"})
@TransactionConfiguration(transactionManager = "transactionManager", defaultRollback = true)
public class UserServiceTest {

  private UserService userService;

  @Test
  public void should_return_true_when_user_is_logged_in ()
          throws Exception
  {
    String[] usernames = {"a","b","c","d"};

    for (String username : usernames)
    {
      userService.logUserIn(username);
      assertThat(userService.isUserLoggedIn(username), is(equalTo(true)));
    }
  }

ApplicationContext-Text.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"&gt;

  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
          <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
          <property name="url" value="jdbc:mysql://localhost:3306/******"/>
          <property name="username" value="*****"/>
          <property name="password" value="*****"/>
  </bean>

  <tx:annotation-driven transaction-manager="transactionManager"/>

  <bean id="userService" class="Service.UserService">
    <property name="userDAO" ref="userDAO"/>
  </bean>

  <bean id="userDAO" class="DAO.UserDAO">
    <property name="hibernateTemplate" ref="hibernateTemplate"/>
  </bean>

  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="mappingResources">
      <list>
        <value>/himapping/User.hbm.xml</value>
        <value>/himapping/setup.hbm.xml</value>
        <value>/himapping/UserHistory.hbm.xml</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
        <prop key="hibernate.show_sql">true</prop>
      </props>
    </property>
  </bean>

  <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"
          p:sessionFactory-ref="sessionFactory"/>

  <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
    <property name="sessionFactory">
      <ref bean="sessionFactory"/>
    </property>
  </bean>

</beans>

I have been reading about the issue, and I've already checked to ensure that the MySQL database tables are setup to use InnoDB. Also I have been able to successfully implement rolling back of transactions outside of my testing suite. So this must be some sort of incorrect setup on my part.

Any help would be greatly appreciated :)

A: 

I hope I am right and that this is a simple one. You are missing the @Transactional annotation on your test class. This means that the test method itself isn't run in a transaction and thus there is nothing to roll back. Hope this helps.

Gennadiy
I added the @Transactional annotation and it is still committing the transactions :(
Trevor
For the sake of being thorough... as mentioned before, I have changed my setup quite a few times, and the setup I have posted above was not showing in the logs that the transactions were rolling back... when I added the @Transactional annotation, it is now showing that the transactions are rolling back in the logs, but it is still committing to the DB.I also had to tweak my libraries a bit, I had to track down version 3.2 of the asm.jar file, as I was getting a "method not found" exception for the ASM library.
Trevor
Trevor, by any chance do you have any transactional annotations or controls in the user service itself. The commit may be due to a REQUIRES_NEW propagation value somewhere on the chain of transactions.Another test i would run is to simply insert a record using the user DAO directly into th DB using a transactional test and make sure it's rolling back. If not something is up with the transaction set up in hibernate. Can you provide more details about what the service does?
Gennadiy
A: 

The problem turned out to be that the connection was auto-committing BEFORE the transaction could be rolled back. I had to change my dataSource bean to include a defaultAutoCommit property:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/test"/>
  <property name="username" value="root"/>
  <property name="password" value="Ecosim07"/>
  <property name="defaultAutoCommit" value="false" /> 
</bean>
Trevor