TestCode 의 properties override 에 대하여
개요
TestCode 의 properties 파일에 대한 오해가 있어서 간단히 정리해보려 한다.
스프링에 대한 실력이 부족해서 업무 중 실수를 했다 ㅠ
다음엔 실수하지 않도록 정리를 해놓자.
내가 하려고 했던 방향
기존의 propeties 파일 및 통합 테스트 어노테이션이다.
@ActiveProfiles("test")
@AutoConfigureTestDatabase
@ExtendWith(SpringExtension.class)
@SpringBootTest
public abstract class NdapSpringIntegrationTestBase {
}
왜 test/application.properties 를 만들지 않고 test/application-test.properties + @ActiveProfiles 를 조합하여 사용하지?
그래 test/application.properties 를 만들고 @ActiveProfiles 는 제거해버리자!!( 실수 )
아래는 PR 에서 받았던 리뷰이다.
음.. 나의 생각은 왜 main/resources/application.properties 를 test package 에서 사용하는 거지..? 라는 의문이 생겼다.
그리고 고정관념? 비슷해서 @SpringBootTest 실행하면 무조건 test/resouces 에 있는 properties 파일을 읽는다고 생각했고 없으면 에러가 나는 줄 알았다... ( 두 번째 실수 )
그러나 없을 시 main/resources/application.properties 파일을 사용했다.
이러한 상황에서 properties 관련한 테스트가 필요했다.
Test 위한 기본 Setting
아래의 2가지 파일을 추가하자.
@Component
public class PropertySourceResolver {
@Value("${example.firstProperty}") private String firstProperty;
@Value("${example.secondProperty}") private String secondProperty;
public String getFirstProperty() {
return firstProperty;
}
public String getSecondProperty() {
return secondProperty;
}
}
<main/resources/application.properties>
example.firstProperty=defaultFirst
example.secondProperty=defaultSecond
그리고 테스트 코드를 작성한다. (test/resouces/application.properties 없는 상태)
main/resources/application.properties 를 읽어온다.
@SpringBootTest
public class TestResourcePropertySourceResolverIntegrationTest {
@Autowired
private PropertySourceResolver propertySourceResolver;
@Test
public void shouldTestResourceFile_overridePropertyValues() {
String firstProperty = propertySourceResolver.getFirstProperty();
String secondProperty = propertySourceResolver.getSecondProperty();
assertEquals("defaultFirst", firstProperty);
assertEquals("defaultSecond", secondProperty);
}
}
Test 1. test/resources/application.properties 추가
아래 파일을 추가하자. 그럼 어떻게 될까?
<test/resources/application.properties>
example.firstProperty=file
example.secondProperty=file
테스트 코드는 통과한다.
String firstProperty = propertySourceResolver.getFirstProperty();
String secondProperty = propertySourceResolver.getSecondProperty();
assertEquals("file", firstProperty);
assertEquals("file", secondProperty);
그럼 test/resources/application.properties 에서 하나의 속성을 지워보자.
example.firstProperty=file
main/resources/application.properties 값을 못 읽어오면서 에러가 발생한다.
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'example.secondProperty' in value "${example.secondProperty}"
따라서 test/resources/application.properties 가 존재하면 main/resources/application.properties 를 사용할 수 없다는 얘기가 된다.
Test 2. test/resources/application-test.properties + @ActiveProfile 추가
그럼 위 상황(main/resources/application.properties, test/resources/application.properties 에 properties 파일이 모두 있는 경우)에서 아래 파일을 추가해보자.
<test/resources/application-test.properties>
example.firstProperty=profile
@ActiveProfiles 를 붙여서 테스트 코드를 작성하자.
@ActiveProfiles("test")
@SpringBootTest
public class TestResourcePropertySourceResolverIntegrationTest {
@Autowired
private PropertySourceResolver propertySourceResolver;
@Test
public void shouldTestResourceFile_overridePropertyValues() {
String firstProperty = propertySourceResolver.getFirstProperty();
String secondProperty = propertySourceResolver.getSecondProperty();
assertEquals("profile", firstProperty);
assertEquals("file", secondProperty);
}
}
결과적으로 firstProperty 는 test/resources/application-test.properties, secondeProperty 는 test/resources/application.properties 에서 읽어 온다.
만약 test/resources/application.properties 가 없다면? 난 에러를 예상했다. 그러나...
firstProperty 는 test/resources/application-test.properties, secondeProperty 는 main/resources/application.properties 에서 읽어왔다.. 즉 기본 파일에 test 파일이 override 되는 형태였다.
결론
두 방법은 비슷해보이지만 목적 자체가 다르다.
1. @ActiveProfiles("test") + test/resources/application-test.properties
- main/resources/application.properties override 하기 위한 목적(필요한 변수만 변경해서 테스트하는 경우 사용)
2. @ActiveProfiles("test") 제거 + test/resources/application.properties
- main/resources/appliaction.properties 와는 별개로 동작(properties 를 main 과 분리하고 싶은 경우 사용)