現象
spring-bootでspring-batchを起動するとデフォルトではjobを自動実行するため、@SpringBootTestでJobLauncherTestUtilsから任意タイミングでjobを起動すると二回実行されてしまった。
対策
spring.batch.job.enabled=false でそのデフォルト挙動を無効にできるので、たとえば@SpringBootTestにテスト用プロパティを追加する。
@SpringBootTest(properties = "spring.batch.job.enabled=false")
再現ソースコードなど
とりあえず適当なspring-batchのjobをつくる。
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '3.5.6'
id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
description = 'Demo project for Spring Boot'
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-batch'
runtimeOnly 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.batch:spring-batch-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
適当なjobを作る。
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.transaction.PlatformTransactionManager;
@SpringBootApplication
public class DemoApplication {
@Bean
Job sampleJob(JobRepository jobRepository, PlatformTransactionManager txManager) {
Step step = new StepBuilder("sampleStep", jobRepository)
.tasklet((contribution, chunkContext) -> {
System.out.println("########### sample job step");
return RepeatStatus.FINISHED;
}, txManager)
.build();
return new JobBuilder("sampleJob", jobRepository)
.start(step)
.build();
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
テストコードを作る。異なるjob実行と認識されるようJobParameterを追加している。
import org.junit.jupiter.api.Test;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
//(properties = "spring.batch.job.enabled=false")
@SpringBatchTest
class DemoApplicationTests {
@Test
void test001(
@Autowired Job job,
@Autowired JobLauncherTestUtils jobLauncher) throws Exception {
jobLauncher.setJob(job);
jobLauncher.launchJob(
new JobParametersBuilder()
.addLong("run.id", System.currentTimeMillis())
.toJobParameters());
}
}
ログを確認するとjobが二回実行されてしまっているのが分かる。
Job: [SimpleJob: [name=sampleJob]] launched with the following parameters: [{}]
....
Job: [SimpleJob: [name=sampleJob]] launched with the following parameters: [{'run.id':'{value=1760059938636, type=class java.lang.Long, identifying=true}'}]