SpringBootTest 어노테이션이 없는 단위 테스트시 @value값이 주입되지 않는 경우가 발생한다.
@Value 어노테이션을 사용하여 설정파일에서 값을 읽어서 사용하는 경우 해당 설정을 테스트 코드에서는 어떻게 읽어와야 하는지에 대한 고민이 생겼다.
테스트 코드에서 @Value값을 읽어오는 몇가지 방법을 찾을 수 있었다.
현재 @Value를 사용하는 PostService class를 테스트하는 PostServiceTest는 SpringBootTest를 사용하지 않는 단위 테스트 이지만, 테스트 프로퍼티 파일 생성과 리플렉션 두가지 방법 모두 시도 해 보았다.
@TestPropertySource는 Spring의 테스트 컨텍스트를 초기화할 때 사용되는 프로퍼티 소스를 지정한다. 이렇게 하면, Spring Boot가 테스트를 실행할 때 해당 프로퍼티 파일을 로드하고, 그 안에 정의된 값을 애플리케이션 컨텍스트의 프로퍼티로 사용하게 된다.
constant-data.modifiable-date-value=10
constant-data.modification-limit-value=5
@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);
}
}
Mockito 환경에서 @Value를 사용하여 설정 파일의 값을 읽어오는 것은 직접적으로 지원되지 않기 때문에 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를 사용하지 않는 단위테스트를 할 수 있었다.
하지만 해당 방법은 설정 파일에서 값을 읽어오는 방식이 아니기 때문에 통합 테스트에서는 어울리지 않는 방식이란 생각이 든다.