개발/spring

[springboot] Test code: profile and configuration

방푸린 2024. 9. 12. 16:37
반응형

환경: springboot3, java17

 

소스를 배포 환경(ex. dev, stage, real...)에 따라 실행할 때 보통 profile 옵션을 줘서 환경에 맞는 프로퍼티 파일을 들고 갈 수 있게 한다.

 $JAVA11_PATH/java -jar -DappName=$APP_NAME -Dspring.profiles.active=$ACTIVE_PROFILE $DEPLOY_DIR/$JAR_NAME 1>/dev/null 2>/dev/null &

 

테스트 코드를 짤 때 필요한 설정파일은 보통 test/resources패키지 안에 application.yml로 만든다.

문득 궁금한 게 어떨 때는 test/resources/application-test.yml로 만들고 어떨 때는 test/resources/application.yml로 만들었던 것 같다.

두 개가 같은 상황으로 인식되나? 궁금해서 파헤쳐 본다.

 

테스트 코드를 위한 프로퍼티 파일

1. test/resources/application.yml로 만들면

테스트가 돌아갈 때 기본적으로 들고 가며 main/resources/application.yml을 덮어쓰는 효과가 난다.

테스트 코드에 아무 설정을 하지 않아도 적용된다.

2. test/resources/application-test.yml로 만들면

테스트 폴더 안에 있지만 어쨌건 profile이 적용된 파일이라 프로파일을 적용해야만 반영된다. 

적용하는 방법은 아래처럼 소스에다 명시한다(모든 소스에다 다 해야 하면 1번 방법을 쓰는 게 낫다.)

@ActiveProfiles("test") // test profile을 적용하라는 뜻
@Import({TestBatchConfig.class})
@SpringBootTest
class DailyRankingJobConfigTest {

혹은 외부에서 주입해야 한다.(위에 jar 실행 시처럼)

 

반대로 해당 빈을 특정 프로파일(ex. test)에서만 사용해야 한다면

1. 빈으로 프로파일을 명시한다.

@Profile("test")
@Configuration

위 설정은 profile=test 일 때만 로드된다.

2. 테스트에서만 사용하는 설정의 경우

프로파일에 상관없이 테스트에서만 사용된다면 아래 어노테이션을 사용하면 된다.

@TestConfiguration

 

사용 예제

즉, 테스트 코드에서 아래 어노테이션을 사용한다면..

@ActiveProfiles("test") 

1. 테스트 코드에서 2. 테스트 프로파일을 불러오는 것이므로

@Profile("test")
@Configuration

가 달린 설정과

@TestConfiguration

가 달린 설정 모두를 불러오게 된다.


추가적으로 궁금한 사항.....

@TestConfiguration
public class TestBatchConfig {
 @Bean
  public JobTestUtils jobTestUtils(){

해당 파일은 테스트 코드가 돌 때 자동으로 빈으로 등록하는 것인데

@ActiveProfiles("test") // test profile을 적용하라는 뜻
@ContextConfiguration(classes = {TestBatchConfig.class}) //or @Import({TestBatchConfig.class})
@SpringBootTest
class DailyRankingJobConfigTest {
		
  @Autowired private JobTestUtils jobTestUtils;

정작 테스트 코드에서 두 번째 줄을 지우면 JobTestUtils 빈을 못 찾아서 테스트가 실패한다. 아니 테스트 코드 설정이라면서 왜정작 못 불러오는 거지..

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'DailyRankingJobConfigTest'
: Unsatisfied dependency expressed through field 'jobTestUtils': No qualifying bean of type 'JobTestUtils' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations:

 

관련하여 spring공식 문서를 보니 아래와 같은 부분이 있다.

정리하면, 일반 클래스(top-level)로 configuration클래스를 만들면 스캐닝되지 않고 inner class에 static으로 만들어야지만 된다는 것...?!

https://docs.spring.io/spring-boot/reference/testing/spring-boot-applications.html#testing.spring-boot-applications.detecting-configuration

 

Testing Spring Boot Applications :: Spring Boot

To test whether Spring MVC controllers are working as expected, use the @WebMvcTest annotation. @WebMvcTest auto-configures the Spring MVC infrastructure and limits scanned beans to @Controller, @ControllerAdvice, @JsonComponent, Converter, GenericConverte

docs.spring.io

그래서 아래처럼 inner class로 만들어보니 진짜 된다..! 이럴 수가

@ActiveProfiles("test") 
@SpringBootTest
class DailyRankingJobConfigTest {
	@Autowired private JobTestUtils jobTestUtils;
    
    ...
    
    
  @TestConfiguration
  public static class TestBatchConfig {

    @Bean
    public JobTestUtils jobTestUtils() {
      return new JobTestUtils();
    }
  }
}

 

하지만 매번 inner class로 넣을 수도 없어서 그냥 Import구문을 넣어야겠다..

728x90
반응형