Spring新手求助:如何解决‘no transaction is in progress’错误
Hey there! I totally get where you're coming from—moving @EnableBatchProcessing to a dedicated config class is a smart move for cleaner slice tests, but that transaction error can be frustrating. Let’s break down why this happens and walk through how to fix it.
Why This Error Pops Up
When @EnableBatchProcessing was on your MyApplication main class, Spring Boot automatically pulled in all the core batch infrastructure beans (like the transaction manager, job repository, and step execution components) as part of the full application context. Once you moved it to a separate config class, your test context might not be loading that config by default—meaning the necessary transaction support components aren’t registered. Without those, when your batch steps try to run within a transaction, there’s no active transaction context to attach to.
Step-by-Step Solutions
Ensure your test loads the batch config class
If you’re using@SpringBootTest, explicitly include your batch config alongside the main application class to guarantee the batch infrastructure is initialized:@SpringBootTest(classes = {MyApplication.class, YourBatchConfig.class}) class MyTest { // ... your test logic here }For slice tests (like testing an ItemWriter or Reader in isolation), use
@Importto bring in the batch config directly:@Import(YourBatchConfig.class) class MyItemWriterTest { // ... your test logic here }Leverage Spring Batch’s dedicated test annotation
Spring Batch provides@SpringBatchTestto simplify batch testing. This annotation automatically sets up test utilities (likeJobLauncherTestUtils) and ensures all critical batch beans (including transaction managers) are available in the test context. Pair it with your context setup:@SpringBatchTest @SpringBootTest(classes = {MyApplication.class, YourBatchConfig.class}) @Transactional class MyBatchJobTest { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; @Test void testJobCompletesSuccessfully() throws Exception { JobExecution execution = jobLauncherTestUtils.launchJob(); assertEquals(BatchStatus.COMPLETED, execution.getStatus()); } }Double-check your batch config annotations
Make sure your batch config class has both@Configurationand@EnableBatchProcessing—missing either will prevent the infrastructure beans from being created. Also, confirm your steps are configured to use a transaction manager (Spring Batch will use a default one if you have aPlatformTransactionManagerbean in the context, like the one provided by Spring Data JPA).Add explicit transaction support to tests
For tests that interact with batch components directly (not running the full job), adding@Transactionalto your test class or method will create an active transaction context. This is especially useful for testing components like ItemWriters that rely on transactions to persist data:@SpringBatchTest @Import(YourBatchConfig.class) @Transactional class MyItemWriterTest { @Autowired private MyItemWriter itemWriter; @Autowired private EntityManager entityManager; @Test void testItemsAreWritten() throws Exception { List<MyData> items = List.of(new MyData("test")); itemWriter.write(items); entityManager.flush(); // Ensure data is persisted within the transaction // Verify the data exists long count = entityManager.createQuery("SELECT COUNT(d) FROM MyData d", Long.class).getSingleResult(); assertEquals(1, count); } }
Quick Recap
The core fix here is making sure your test context includes the batch configuration with @EnableBatchProcessing, so all required transaction and batch infrastructure beans are loaded. Using @SpringBatchTest takes most of the guesswork out of setting up a proper test environment for batch jobs.
内容的提问来源于stack exchange,提问作者Javaron

