Spring Boot Test에서 @Value 어노테이션 처리 방법

HMS·2024년 1월 14일

Spring Boot Test에서 @Value 어노테이션 처리 방법

SpringBootTest 어노테이션이 없는 단위 테스트시 @value값이 주입되지 않는 경우가 발생한다.
@Value 어노테이션을 사용하여 설정파일에서 값을 읽어서 사용하는 경우 해당 설정을 테스트 코드에서는 어떻게 읽어와야 하는지에 대한 고민이 생겼다.

테스트 코드에서 @Value값을 읽어오는 몇가지 방법을 찾을 수 있었다.

방식

  1. 테스트용 프로퍼티 파일 생성 : 테스트 리소스 디렉토리에 별도의 프로퍼티파일인 application-test.yml을 생성한 후 테스트 실행시 해당 파일을 사용하도록 구성하는 방법이다.
  2. ReflectionTestUtils 사용 : Spring 테스트 프레임워크에서 제공하는 유틸리티 클래스로 Private 필드에 직접 접근하여 값을 설정할 수 있게 해준다.
  3. @Value 어노테이션이 붙은 메소드를 Mocking 하기

현재 @Value를 사용하는 PostService class를 테스트하는 PostServiceTest는 SpringBootTest를 사용하지 않는 단위 테스트 이지만, 테스트 프로퍼티 파일 생성과 리플렉션 두가지 방법 모두 시도 해 보았다.

1. 테스트용 프로퍼티 파일 생성

@TestPropertySource는 Spring의 테스트 컨텍스트를 초기화할 때 사용되는 프로퍼티 소스를 지정한다. 이렇게 하면, Spring Boot가 테스트를 실행할 때 해당 프로퍼티 파일을 로드하고, 그 안에 정의된 값을 애플리케이션 컨텍스트의 프로퍼티로 사용하게 된다.

  1. 테스트 리소스 디렉토리에 (src/test/resources/application-test.yml) 프로퍼티 파일을 생성한다.
  2. 필요한 설정을 추가한다. 현재 설정에서 가져오는 상수 값을 설정해 주었다.
constant-data.modifiable-date-value=10
constant-data.modification-limit-value=5
  1. 테스트 클래스에서 프로퍼티 파일 지정 : @TestPropertySource어노테이션을 사용하여 테스트용 프로퍼티 파일을 지정한다.
@SpringBootTest
@TestPropertySource("classpath:application-test.yml")
class PostServiceTest {

    @Autowired
    private PostService postService;

    @DisplayName("getModifiableDate 성공 테스트")
    @Test
    void getModifiableDate() {
        // given
        LocalDateTime testDate = LocalDateTime.of(2023, 11, 29, 0, 0);
        // when
        Long result = 10 - ChronoUnit.DAYS.between(testDate, now);
        // then
        assertThat(postService.getModifiableDate(testDate)).isEqualTo(result);
    }
}
  • 결과 : 해당 방식을 사용하면 @SpringBootTest 를 실행할 때 정상적으로 설정파일의 상수값을 가져올 수 있었다. 하지만 @InjectMocks을 사용하여 모킹 객체를 사용하고 단위테스트를 하는 환경에서는 다른 접근방법이 필요했다.

2. ReflectionTestUtils 사용

Mockito 환경에서 @Value를 사용하여 설정 파일의 값을 읽어오는 것은 직접적으로 지원되지 않기 때문에 ReflectionTestUtils를 사용하여 테스트 중인 서비스에 필요한 필드 값을 직접 설정할 수 있었다.

  1. ReflectionTestUtils를 사용하여 필드 값을 설정
@ExtendWith(MockitoExtension.class)
class PostServiceTest {

    @InjectMocks
    private PostService postService;

    @BeforeEach
    void setUp() {
        // modifiableDateValue 값을 10으로 설정
        ReflectionTestUtils.setField(postService, "modifiableDateValue", 10);
    }
    
    @DisplayName("getModifiableDate 성공 테스트")
    @Test
    void getModifiableDate() {
        // given
        LocalDateTime testDate = LocalDateTime.of(2023, 11, 29, 0, 0);
        // when
        Long result = 10 - ChronoUnit.DAYS.between(testDate, now);
        // then
        assertThat(postService.getModifiableDate(testDate)).isEqualTo(result);
    }

결론

postService 클래스의 modifiableDateValue 필드에 직접 값을 설정함으로써, Mockito환경에서 SpringBootTest를 사용하지 않는 단위테스트를 할 수 있었다.
하지만 해당 방법은 설정 파일에서 값을 읽어오는 방식이 아니기 때문에 통합 테스트에서는 어울리지 않는 방식이란 생각이 든다.

profile
안녕하세요

0개의 댓글