Home > database >  Rollback not working on Spring Boot @Transactional method for H2 database
Rollback not working on Spring Boot @Transactional method for H2 database

Time:07-24

Please give me tips to get my failing JUnit test to pass in my Spring Boot app.

I have a Service that needs to delete rows from tables A and B (from a H2 database) in a transactional manner such that: if A is modified and then an exception occurs before B is modified, then neither A nor B are modified. However, even after 

  1. Adding @Transactional to the PUBLIC Service::deleteRows method, and
  2. Adding @EnableTransactionManagement to the @Configuration class that produces the JdbcTemplate that all repositories use, and
  3. Confirming that spring-tx is on the classpath

the transaction still doesn't rollback.

Here's the failing JUnit testcase

// Service.java
@Transactional
public void deleteRows() {
    aRepository.deleteRow(123);
    bRepository.deleteRow(123);
}
// ServiceTest.java
@Test
void test() {​
    // first ensure that an exception is thrown when bRepository.deleteRow() is called
    // FYI deleteRow() calls jdbcTemplate.update()
    doThrow(RuntimeException.class)
        .when(mockJdbcTemplate)
        .update(any(), eq(123));
    BRepository mockBRepository = new BRepository(mockJdbcTemplate);
    Service service = new Service(realARepository, mockBRepository);

    assertTableHasRows(1, "TABLE_A");                          // before calling the service, TABLE_A has 1 row

    assertThrows(RuntimeException.class, service::deleteRows);    

    assertTableHasRows(1, "TABLE_A");                          // TABLE_A should still have 1 row when an exception occurs during the tx
}​

CodePudding user response:

Remove @Transactional and run test again.

CodePudding user response:

In the end the problem was solved by NOT using mocking to trigger an exception. Instead, we set up the database schema so that normal operation of service::deleteRows would trigger an exception.

  • Related