Suresh Payankannur

Tuesday, April 10, 2012

MySQL and Spring Transactional Tests

For years, I have been using the Transaction support provided by the Spring test framework to write transaction aware unit tests. In the early days, it was by extending AbstractTransactionalSpringContextTests, which was replaced later with the introduction of Test Contexts. Now a days, just by annotating the class with TransactionConfiguration will trigger the transaction listeners to manage the class level or method level transactions. Where @Transaction annotation is used either at the class or method level.

Recently I was doing a new project using JPA, Hibernate, Spring and MySQL and building a generic unit test framework for it. The standard way I have been configuring MySQL with Hibernate was by using org.hibernate.dialect.MySQLDialect. But this was giving strange problems when running transactional unit test cases. The @Rollback(true) annotation was not working at all. At the end of the tests case, what ever database changes are made, they were committed to the database, as if the Rollback annotation do not have any effect at all. I was creating the schema, including tables using Hibernate's schema script creation APIs.

After searching for a solution, finally I found that in the later versions of Hibernate, there are additional dialects for MySQL. There are two more dialects added, MySQLInnoDBDialect and MySQL5InnoDBDialect. So the old usage with org.hibernate.dialect.MySQLDialect will create ISAM tables, which are not transactional. When the dialect was switched to one of InnoDB dialects, the CREATE TABLE scripts emit additional ENGINE=InnoDB clause to the DDLs. And the transactions were rolled back properly at the end of the test case.

Spring Configuration


  

    
    
    
    
    
    
    
    
  

  
    

    
      
        TestModel
      
    

    
      
        ${testdb.hibernate.dialect}
      
    
  

  
    
  

Property File

jdbc.testdb.username     = user
jdbc.testdb.password     = pass
jdbc.testdb.url          = jdbc:mysql://localhost/testdb
jdbc.testdb.driver       = com.mysql.jdbc.Driver
testdb.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect

Test Class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test-config.xml"})
@TransactionConfiguration(transactionManager="txManager", defaultRollback=false)
public class DaoTest {

    @Before
    @BeforeTransaction
    public void setup() {
        dbCreator.createSchema();
    }

    @Test
    @Transactional
    @Rollback(true)
    public void testSave() {
        TestModel model = createNewModel();

        dao.save(model);
    }

0 comments:

Post a Comment

Blog Archive

Scroll To Top