You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch中Tasklet抛异常但assertThrows测试失败问题求助

Spring Batch任务抛出异常但测试断言失败的问题

我在Tasklet的execute()方法中根据条件抛出IllegalStateException,并编写了如下测试用例验证批处理作业:

@Test
void testJobThrowsMyException() throws Exception {
        JobParameters emptyJobParameters = new JobParameters();

        assertThrows(IllegalStateException.class, () -> jobLauncherTestUtils.launchJob(emptyJobParameters));
}

execute方法代码如下:

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
        getWorkload(chunkContext).forEach(workloadItem -> {
            // Processing 
        });

        return RepeatStatus.FINISHED;
    }

获取workload的逻辑大致如下:

private int getWorkload() {
        if (condition) {
            throw new IllegalStateException("Thats the exception i want to test");
        }
        
        return workload;
    }

问题在于,从测试执行日志可以看到异常已抛出,但测试却失败,提示:

org.opentest4j.AssertionFailedError: Expected java.lang.IllegalStateException to be thrown, but nothing was thrown.

日志明确显示异常已抛出:

10:32:54.608 [main] DEBUG org.hibernate.loader.Loader - Result row: 
10:32:54.616 [main] DEBUG org.springframework.batch.core.step.tasklet.TaskletStep - Applying contribution: [StepContribution: read=0, written=0, filtered=0, readSkips=0, writeSkips=0, processSkips=0, exitStatus=EXECUTING]
10:32:54.616 [main] DEBUG org.springframework.batch.core.step.tasklet.TaskletStep - Rollback for RuntimeException: java.lang.IllegalStateException: Es ist noch keine Liefernummer in den ImportDetails vorhanden.
10:32:54.618 [main] DEBUG org.springframework.transaction.support.TransactionTemplate - Initiating transaction rollback on application exception
java.lang.IllegalStateException: Thats the exception i want to test
at [...]
10:32:54.619 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Initiating transaction rollback
10:32:54.619 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Rolling back JPA transaction on EntityManager [SessionImpl(1793816221<open>)]
10:32:54.619 [main] DEBUG org.hibernate.engine.transaction.internal.TransactionImpl - rolling back
10:32:54.620 [main] DEBUG org.springframework.orm.jpa.JpaTransactionManager - Closing JPA EntityManager [SessionImpl(1793816221<open>)] after transaction
10:32:54.621 [main] DEBUG org.springframework.batch.repeat.support.RepeatTemplate - Handling exception: java.lang.IllegalStateException, caused by: java.lang.IllegalStateException: Es ist noch keine Liefernummer in den ImportDetails vorhanden.
10:32:54.621 [main] DEBUG org.springframework.batch.repeat.support.RepeatTemplate - Handling fatal exception explicitly (rethrowing first of 1): java.lang.IllegalStateException: Es ist noch keine Liefernummer in den ImportDetails vorhanden.
10:32:54.622 [main] ERROR org.springframework.batch.core.step.AbstractStep - Encountered an error executing step my-step in job my-job

我并未捕获该异常,请问为何测试会失败?望解答,谢谢。


原因分析

Spring Batch在执行完整作业时,会将任务流程封装在事务管理和异常处理逻辑中。当Tasklet抛出IllegalStateException后,框架会先触发事务回滚,随后不会将原始异常直接抛给jobLauncherTestUtils.launchJob()的调用者,而是把异常信息封装到返回的JobExecution对象中。

launchJob()方法本身不会抛出业务代码产生的异常,只会返回包含失败状态和异常详情的JobExecution实例,这就是assertThrows断言失败的核心原因——没有异常从该方法直接抛出。

解决方案

你需要通过JobExecution的状态和异常信息来验证测试结果,而非直接断言方法抛出异常:

@Test
void testJobThrowsMyException() throws Exception {
    JobParameters emptyJobParameters = new JobParameters();
    JobExecution jobExecution = jobLauncherTestUtils.launchJob(emptyJobParameters);

    // 验证作业执行状态为失败
    Assertions.assertEquals(BatchStatus.FAILED, jobExecution.getStatus());
    // 验证失败原因是目标异常
    Assertions.assertInstanceOf(IllegalStateException.class, jobExecution.getAllFailureExceptions().get(0));
    // 可选:验证异常消息匹配
    Assertions.assertEquals("Thats the exception i want to test", jobExecution.getAllFailureExceptions().get(0).getMessage());
}

如果希望直接捕获到原始异常,可以改为测试单个步骤——launchStep()方法会将步骤执行时抛出的异常直接向上传递:

@Test
void testStepThrowsMyException() throws Exception {
    JobParameters emptyJobParameters = new JobParameters();
    Assertions.assertThrows(IllegalStateException.class, () -> jobLauncherTestUtils.launchStep("my-step", emptyJobParameters));
}

内容的提问来源于stack exchange,提问作者Manu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 21:20:33