Spring: Persistence Test – Commit or Rollback?

Recently I was discussing Persistence tests with a few folks here at Intelliware.
The debate on the table…Commit or rollback?

It was almost evenly split down the middle. But even within that I found a lot of differences in how each project is handling this.

Sampling:

  • On the last project I was on we tested against the real database, did some hibernate flushes in tests but always rolled back at the end of each test so nothing was ever committed.
  • The project I’m currently on the strategy is commit, assert, the clean up the database for each test class (however we unit test on HSQL not the real database)
  • Another project I talked to also used HSQL, committed, and never cleaned up the database. This required a different approach to some testing as your database can be dirty during your tests so you can’t rely on things like explicit row counts.
  • Another project took a more innovative approach and override the jdbc driver, commit but then at the end of the test essentially revert to a save point in the database. (Commit and rollback wrapped in one!)

Given how split projects are and even the people in our room are split, I thought maybe the Spring TestContext Framework  would allow a project to support tests in either commit or rollback.

In the cases you’d like to commit you could and in the places where you’d like to rollback you could also do that.

Here’s a simple hibernate creation test that helps demonstrates the capabilities of the framework in both ways.

Commit:

@Autowired //get from spring
private UserDao userDao;

@Test
public void testCreateUser() {
      Long userId = new Long(1);

      //SUT: System Under Test
      createUserAndCommit(userId);

      Assert.assertEquals(1, simpleJdbcTemplate.queryForInt("select count(*) from user;");

      //Cleanup
      deleteUser(userId);

      Assert.assertEquals(0, simpleJdbcTemplate.queryForInt("select count(*) from user;");
}

@Transactional
@Rollback(false)
private void createUserAndCommit(Long userId) {
      User user = new User(userId);
      user.setName("TEST");
      userDao.save(user);
}

@Transactional
@Rollback(false)
private void deleteUser(Long userId) {
      userDao.delete(id);
}

Rollback:

@Autowired //get from spring
private UserDao userDao;

@Autowired //get from spring
private SessionFactory sessionFactory;

@Test
@Transactional //By default will ROLLBACK
public void testCreateUser() {
      Long userId = new Long(1);

      User user = new User(userId);
      user.setName("TEST");
      userDao.save(user);

      //Flush may not be necessary depending on how the propogation is defined (you can change this in annotations)
      Session session = sessionFactory.getCurrentSession()
      session.flush();

      Assert.assertEquals(1, simpleJdbcTemplate.queryForInt("select count(*) from user;");

      //No need to cleanup as this will rollback.
}

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply