Insert test record for Spring Batch integration test with @Transactional(propagation = NOT_SUPPORTED) does not roll back

Viewed 243

I would like to insert a test record while testing my Spring Batch job.

Normally I'd annotate the test class with @Transactional, but that does not work with a test class that is annotated with @SpringBatchTest.

@SpringBatchTest
@SpringBootTest
@Transactional
public class JobTest {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    void someTest() throws Exception {
        jdbcTemplate.update("insert into some_table (some_col1, some_col2) values ('foo', 'bar')");
        jobLauncherTestUtils.launchJob();
    }
}
Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).
java.lang.IllegalStateException: Existing transaction detected in JobRepository. Please fix this and try again (e.g. remove @Transactional annotations from client).
    at org.springframework.batch.core.repository.support.AbstractJobRepositoryFactoryBean$1.invoke(AbstractJobRepositoryFactoryBean.java:177)

I have also tried @Transactional(propagation = NOT_SUPPORTED), but the record does not rollback. This was the suggestion in https://stackoverflow.com/a/46546171/10243546

I just want test records for the test, so I wasn't sure if this answer applies (https://stackoverflow.com/a/55001568/10243546) since this is just for a test.

2 Answers

You need to move test setup outside the test method, for example in a method annotated with @Before (JUnit 4) or @BeforeEach (JUnit 5). Something like:

@Before
public void initData() {
   jdbcTemplate.update("insert into some_table (some_col1, some_col2) values ('foo', 'bar')");
}

@Test
void someTest() throws Exception {
   jobLauncherTestUtils.launchJob();
}

I was able to get such a test running using TransactionTemplate in the test method:

@SpringBatchTest
class MyJobTest {

  // [...]

  @Autowired
  PlatformTransactionManager txManager;

  @Test
  void some_test() {
    // setup must be done in a custom transaction due too @SpringBatchTest
    new TransactionTemplate(txManager).executeWithoutResult(t -> {
      // use jdbcTemplate or entityManager to insert data
      jdbcTemplate.update("insert into some_table (some_col1, some_col2) values ('foo', 'bar')");
    });

    jobLauncherTestUtils.launchJob();
  }
}
Related