Skip to content
Advertisement

Spring repository : Junit test succeeds on custom delete even when @Transactional is missing

I have a Spring repository that has a method like this :

 Long deleteByStatusAndTriggeredBefore(String status, Timestamp triggered);

When testing this method in a Junit Test, it does work as intended.

@DataJpaTest
public class AlertRepositoryTest {

    @Autowired
    @Qualifier("alertRepository")
    private AlertRepository underTest;

    @AfterEach
    void tearDown(){
        underTest.deleteAll();
    }

    @Test
    void testUpdateAndDelete() {
        Timestamp triggered = java.sql.Timestamp.valueOf("2007-09-23 10:10:10.0");
        Timestamp fixed = java.sql.Timestamp.valueOf("2012-09-23 10:10:10.0");

        Alert alert1 = new Alert("FIXED", "event1", 0L, 0L, triggered, fixed, "domain1", "service1", "metric1", "context1", 1L, 1L);
        Alert alert2 = new Alert("FIXED", "event2", 0L, 0L, triggered, fixed, "domain2", "service2", "metric2", "context2", 1L, 1L);

        underTest.save(alert1);
        underTest.save(alert2);
        
        // some other assertions ...

        // As expected, the elements get deleted and the database is empty
        Timestamp deletion = java.sql.Timestamp.valueOf("2019-09-23 10:10:10.0");
        underTest.deleteByStatusAndTriggeredBefore("FIXED", deletion);
        Page<Alert> alertReturned = underTest.findByStatus("FIXED", Pageable.unpaged());
        assertThat(alertReturned.getContent().size()).isEqualTo(0);  

    }
}

However, the delete does not work on our production DB. For it to work on the production DB, we had to add the @Transactional annotation to the method in the repository

@Transactional
Long deleteByStatusAndTriggeredBefore(String status, Timestamp triggered);

This is an issue as the test works but it does not work in production. Is it possible to make this test fail when there is a transactional annotation missing? The tests are configured to run on an in-memory H2 database.

Answer

The reason it works in tests is that the @DataJpaTest annotation contains the @Transactional meta-annotation. So the whole test method is covered with a transaction, and this allows AlertRepository methods to run without errors.

If you want to make it fail in tests, you can override the @Transactional annotation, as follows:

DataJpaTest
@Transactional(propagation = Propagation.NOT_SUPPORTED)
class MyNonTransactionalTests {

    // ...

}

See the documentation for more information on this behavior.

Advertisement