예제로 배우는 핵심 Spring Batch

Ch08. 좋은 코드의 기본 테스트 코드 작성하기

webmaster 2023. 6. 11. 23:54
728x90

초기 설정

build.gradle

dependencies {
	//...
    testRuntimeOnly 'com.h2database:h2'
}

SpringBatchTestConfig

/**
 * 배치 전역에서 사용하기 위한 config
 */
@Configuration
@EnableAutoConfiguration
@EnableBatchProcessing
public class SpringBatchTestConfig {

}
  • test 의존성에는 h2 Database를 사용할 것이므로 build.gradle 파일에 Import 한다.
  • Test 코드에서 전역으로 사용할 설정 파일을 생성한다.
  • 여기서는 특별한 일을 하지는 않는다

DataBase를 사용하지 않는 Test

HelloWorldJobConfigTest

@RunWith(SpringRunner.class)
@SpringBatchTest
@SpringBootTest(classes = {SpringBatchTestConfig.class, HelloWorldJobConfig.class})
class HelloWorldJobConfigTest {

  @Autowired
  private JobLauncherTestUtils jobLauncherTestUtils;
  @Test
  public void success() throws Exception {
    //when
    JobExecution execution = jobLauncherTestUtils.launchJob(); //배치 실행
    //then
    Assertions.assertEquals(execution.getExitStatus(), ExitStatus.COMPLETED);
  }


}
  • Test 코드는 given, when, then 순으로 실행한다.
  • 전역으로 설정한 SpringBatchTestConfig 클래스와, 테스트로 사용할 HelloWorldJobConfig를 빈으로 등록한다.
  • JobLaucherTestUtils 빈을 주입 받은 뒤, 해당 빈의 launchJob() 메서드를 통해 batch를 실행한다.
    • JobLaucherTestUtils 같은 경우, Job 테스트를 도와주는 Util 클래스이다.
  • 여기서는 Job이 정상적으로 실행이되어 ExitStatus.COMPLETED 값을 반환하는지만 확인한다.

DataBase를 사용하는 Test

applictation.yml

#default
spring:
  profiles:
    active: local

---
spring:
  config:
    activate:
      on-profile: local
  batch:
    job:
      name: ${job.name:NONE}
    jdbc:
      initialize-schema: always # ?????
  datasource:
    url: "jdbc:h2:mem:batch;DB_CLOSE_ON_EXIT=FALSE"
    username: "sa"
    password: ""
    driver-class-name: org.h2.Driver
  jpa:
    show-sql: true

---
spring:
  config:
    activate:
      on-profile: test
  jpa:
    database: h2

TrMigrationConfigTest

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@SpringBatchTest
@SpringBootTest(classes = {SpringBatchTestConfig.class, TrMigrationConfig.class})
class TrMigrationConfigTest {

  @Autowired
  private JobLauncherTestUtils jobLauncherTestUtils;

  @Autowired
  private OrdersRepository ordersRepository;

  @Autowired
  private AccountsRepository accountsRepository;


  @AfterEach
  public void cleanUpEach(){
    //테스트 케이스별 독립적으로 실행이 가능하다.
    ordersRepository.deleteAll();
    accountsRepository.deleteAll();
  }
  @Test
  public void success_noData() throws Exception {
    //when
    JobExecution execution = jobLauncherTestUtils.launchJob();

    //then
    Assertions.assertEquals(execution.getExitStatus(), ExitStatus.COMPLETED);
    Assertions.assertEquals(0, accountsRepository.count());

  }

  @Test
  public void success_existData() throws Exception {
    //given
    Orders orders1 = new Orders(null, "kakao gift", 15000, new Date());
    Orders orders2 = new Orders(null, "naver gift", 13000, new Date());

    ordersRepository.save(orders1);
    ordersRepository.save(orders2);

    //when
    JobExecution execution = jobLauncherTestUtils.launchJob();

    //then
    Assertions.assertEquals(execution.getExitStatus(), ExitStatus.COMPLETED);
    Assertions.assertEquals(2, accountsRepository.count());
  }
}
  • yml 파일에서 default 실행은 local 설정을 따르도록 설정하였다.(spring.profiles.active: local)
  • Test 파일에서 @ActiveProfiles 어노테이션에 "test"를 주어 test 환경에서 실행하도록 하였다.
  • success_noData 테스트에서는 Data가 없을 경우에 테스트를 진행한 것이다.
  • success_existData 테스트에서는 Data를 넣고(2개), 테스트를 진행하였다.
  • 각각의 테스트를 독립적으로 실행하기 위해 @AfterEach를 사용해 해결했다.
    • success_existData가 실행되고, success_noData가 실행이 되면 오류가 발생했다(success_existData 테스트에 success_noData 테스트가 영향을 받는다)
    • @AfterEach 어노테이션을 통해, 모든 Test가 실행된 이후, Repository의 Data들의 모두 지워주었다.
728x90