thumbnail

이슈

@Value를 통해서 application.ymlproperties를 주입 할 수 있습니다.

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>

아름다운 것은 생성자를 통해 이를 주입하면 좋겠습니다.
따라서, @RequireAgrsConstructorfinal키워드를 사용합니다.

@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);
    //...
}
CommentCount 0
이전 댓글 보기
등록
TOP