단위테스트에서, @Value 좀 더 이쁘게 쓰기
이슈
@Value
를 통해서 application.yml
의 properties
를 주입 할 수 있습니다.
public class AClass {
@Value("${app.blabla.value.a}")
private Integer valueA;
@Value("${app.blabla.value.b}")
private Integer valueB;
@Value("${app.blabla.value.c}")
private Integer valueC;
}
<br>
불편한점은, 단위 테스트코드
작성 시 발생합니다.
@Value
로 지정된 private 멤버 변수
에 주입구를 열어주어야합니다.
<br>
첫번째, setter
를 쓸 수 있습니다.
하지만 setter
는 곧 변경가능성을 의미합니다.
setter
를 제공하면, 생성 후 유동적으로 내부 값을 바꾸게 할 수 있습니다.
변경가능성은 추후 문제를 유발 할 수도 있습니다.
<br>
두번째, ReflectionTestUtils
를 사용할 수도 있습니다.
@Test
public void test(){
AClass aclass = new AClass();
ReflectionTestUtils.setField(aClass, "vlaueA", 1);
ReflectionTestUtils.setField(aClass, "vlaueB", 2);
ReflectionTestUtils.setField(aClass, "vlaueC", 3);
//...
}
하지만 리플렉션을 사용하는 것은 최후의 보루입니다.
Reflection should really only be a last resort.
https://stackoverflow.com/questions/2811141/is-it-bad-practice-to-use-reflection-in-unit-testing
<br>
아름다운 것은 생성자를 통해 이를 주입하면 좋겠습니다.
따라서, @RequireAgrsConstructor
와 final
키워드를 사용합니다.
@RequireAgrsConstructor
public class AClass {
@Value("${app.blabla.value.a}")
private final Integer valueA;
@Value("${app.blabla.value.b}")
private final Integer valueB;
@Value("${app.blabla.value.c}")
private final Integer valueC;
}
그리고 에러가 발생합니다..
Parameter 0 of constructor in com.podo.pododev.Aclass required a bean of type 'java.lang.Integer' that could not be found.
문제는 @RequireAgrsConstructor
로 생성자를 생성하면,
생성자의 인자에 @Value
가 주입되지 않기 때문입니다.
<br>
그럼 생성자를 수동을 만들어주는 것입니다.
하지만 멤버변수가 많다면 어떨까요? (지저분..)
public class XClass {
private final Integer valueA;
private final AClass aClass;
private final BClass bClass;
private final CClass cClass;
private final DClass dClass;
private final EClass eClass;
public AClass(
@Value("${app.blabla.value.a}") Integer valueA,
AClass aClass,
BClass bClass,
CClass cClass,
DClass dClass,
EClass eClass,
){
this.valueA = valueA;
this.aClass = aClass;
this.bClass = bClass;
this.cClass = cClass;
this.dClass = dClass;
this.eClass = eClass;
}
}
<br>
이쁘게 이쁘게.
lombok.config
를 이용합니다.
<br>
프로젝트 최상단에 lombock.config
를 생성합니다.
<img src="https://static.podo-dev.com/blogs/images/2020/03/12/origin/c4bcbc28-5eb3-43bf-870d-da084ffed2e0.png" alt="base64.png" style="width:188px;">
다음 코드를, 작성합니다.
lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Value
<br>
그리고 @RequireAgrsConstructor
를 통해, 생성자를 만듭니다.
@RequireAgrsConstructor
public class AClass {
@Value("${app.blabla.value.a}")
private final Integer valueA;
@Value("${app.blabla.value.b}")
private final Integer valueB;
@Value("${app.blabla.value.c}")
private final Integer valueC;
}
<br>
빌드 후, AClass.class
파일을 보면
생성자의 인자에 @Value
어노테이션이 주입되어 있습니다.
더 이상 에러가 발생하지 않습니다.
// AClass.class
public class AClass {
@Value("${app.blabla.value.a}")
private final Integer valueA;
@Value("${app.blabla.value.b}")
private final Integer valueB;
@Value("${app.blabla.value.c}")
private final Integer valueC;
public AClass(
@Value("${app.blabla.value.a}") Integer valueA,
@Value("${app.blabla.value.b}") Integer valueB,
@Value("${app.blabla.value.c}") Integer valueC
){
this.valueA = valueA;
this.valueB = valueB;
this.valueC = valueC;
}
}
<br>
단위 테스트코드
를 다음과 같이 작성 할 수 있습니다.
깔끔합니다. 이쁩니다.(!)
@Test
public void test(){
AClass aclass = new AClass(1, 2, 3);
//...
}