Post

Spring Batch 테스트 환경 구축(With Redis)

Spring Batch 테스트 환경 구축(With Redis)

개요

spring-batch는 사용하지만 테스트코드는 일절없는 환경. 테스트 코드를 작성할 수 있는 환경이 필요(성능 테스트 등을 위하여)

환경: spring-boot : 2.7.4

  1. 의존성 추가

spring-boot-starter-test : Junit사용 때문 spring-batch-test: SpringBatchTest 애노테이션 사용 h2: JobLauncher가 사용할 테스트용 데이터베이스

  1. 실행할 배치Job에 대한 테스트 코드 작성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// For Junit
@RunWith(SpringRunner.class)
@SpringBatchTest
@SpringBootTest(classes = {TestBatchConfig.class, SampleJob.class}) //Batch 설정와 테스트할 Job을 추가합니다.
@Import({TestRedisConfig.class}) // Redis 셋팅
@ActiveProfiles("test")
public class BatchSimpleTest {

    @MockBean
    EnvService envService;

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void 테스트코드_샘플() throws Exception {
        //given
        JobParameters jobParameter =  new JobParametersBuilder().toJobParameters();

        //when
        JobExecution jobExecution = jobLauncherTestUtils.launchJob(jobParameter);

        //then
        Assertions.assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED);

    }

}

여기서 별도로 작성해줘야할 클래스들은 TestBatchConfig.classSampleJob.class ,TestRedisConfig 입니다.

TestBatchConfig.class의 용도는

조졸두님의 https://jojoldu.tistory.com/455 해당 글을 보는게 더 도움이 될 듯합니다.

1
2
3
4
5
6
//TestBatchConfig.class
@Configuration
@EnableAutoConfiguration
@EnableBatchProcessing
public class TestBatchConfig {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//TestRedisConfig
public class TestRedisConfig {

    @Value("${spring.redis.nodes}")
    private String[] nodes;

    @Value("${spring.redis.password}")
    private String password;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        ClusterServersConfig clusterServer = config.useClusterServers();
        clusterServer.setScanInterval(2000);
        clusterServer.addNodeAddress(nodes);
        clusterServer.setReadMode(ReadMode.MASTER);
        clusterServer.setPassword(password);
        clusterServer.setMasterConnectionMinimumIdleSize(5);
        clusterServer.setMasterConnectionPoolSize(50);
        clusterServer.setSlaveConnectionMinimumIdleSize(5);
        clusterServer.setSlaveConnectionPoolSize(50);

        config.setCodec(OcJsonJacksonCodec.INSTANCE);
        return Redisson.create(config);
    }
}

회사 기준 서버 구성이라 Redis가 클러스터링되어있습니다. 각자 환경에 맞게 코드를 수정하면 될 것 같습니다. 이 부분은 각자 환경에 따라 구성이 달라질 것이라 따로 설명 드리지는 않겠습니다.

SampleJob.class의 경우에는 실제 사용할 Job을 넣지만 저는 테스트용으로 하나 만들어서 넣었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Slf4j
@TestConfiguration
public class SampleJob {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;

    @Autowired
    private StepBuilderFactory stepBuilderFactory;

    @Bean(name = "testSampleJob")
    public Job sampleJob() {
        return jobBuilderFactory.get("sampleJobTest")
                .incrementer(new RunIdIncrementer())
                .start(sampleStep())
                .build();

    }

    @Bean
    public Step sampleStep() {
        int i = 0;
        return stepBuilderFactory.get("sampleStepTest")
                .<Integer, String>chunk(200)
                .reader(new ItemReader<Integer>() {
                    private int count = 0;

                    @Override
                    public Integer read() {
                        count++;
                        if (count < 500) {
                            return i;
                        } else {
                            return null;
                        }
                    }
                })
                .writer(items -> log.info(" >>> {}", items.size()))
                .build();
    }
}

해당 Job은 200개씩 데이터를 읽고 500개째에서 Job을 종료하는 간단한 로직입니다.

  1. 실행할 배치에 대한 Profile 작성

다른 Profile로 테스트를 돌리면 알 수 없는데서 충돌이 나거나 오류가 날 수 있으므로 따로 Profile(@ActiveProfiles(“test”))을 적용하였습니다.

따라서 이에 맞춘 설정 값들을 적용시켜줘야합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# application-test.yml
spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
    username: sa
    password:
  redis:
    nodes: 
    password: 
  h2:
    console:
      enabled: true
logging:
  level:
    root: INFO
  config: classpath:logback-test.xml

여기서 또한 log에대한 설정도 따로 지정해줬기에 같은 test/resources에 logback-test.xml을 작성해줍니다.

1
2
3
4
5
6
7
8
9
10
11
<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="CONSOLE" />
    </root>
</configuration>

자, 이제 통합테스트를 위한 구성은 모두 마무리되었습니다.

이제 테스트코드를 실행해서 확인해봅니다.

성공하였습니다.

저는 회사의 모종의 이유를 레디스를 직접 붙어서 사용하게 되었는데, Mocking을 하거나 테스트용 컨테이너 레디스를 올려서 진행해도 되니 참고하면 될 것 같습니다.

This post is licensed under CC BY 4.0 by the author.