인프런 커뮤니티 질문&답변

메모장님의 프로필 이미지
메모장

작성한 질문수

스프링 핵심 원리 - 기본편

다양한 의존관계 주입 방법

필드 주입의 문제점에 대해 궁금한게있습니다.

작성

·

468

1

20:20 정도부터 나오는 필드주입에서 궁금한점이 있습니다.

김영한님 말씀중에선 강의예제중, 

@Autowired private MemberRepository memberRepository;
@Autowired private DiscountPolicy discountPolicy;

위처럼 필드주입을 하게되면 memberRepository  나discountPolicy  의 값을 변경할수없고 테스트코드에서  순수한 자바로 테스트할수있는 방법이 없다고 하셨습니다.

그런데 제 생각으로는 그렇게 생각하면 기본방법인 생성자 주입도 결국 생성되고나면 변경할수없고 순수한 자바로 테스트할수있는 방법이 없는것 같다고 생각이 되었습니다. 왜냐면 둘다 현재 수동설정이 아닌 어노테이션을 통한 자동설정으로 이루어지고있으므로 무얼 넣어줄지는 해당 구현체의 어노테이션을 추가,삭제해주지않는이상 바꿀수 없다고 생각했기 때문입니다.

이부분에대해서 설명주시면 감사하겠습니다!

답변 1

3

안녕하세요. 메모장님, 공식 서포터즈 David입니다.

.

순수한 자바로 테스트한다는 말을 잘 생각해보시면 좋습니다.
스프링 컨테이너를 실행하지 않은 상태(필드 주입을 위한 @Autowired가 동작하지 않음)에서는 생성자나 수정자가 없으면 필드에 구현체를 넣을 방법이 없습니다.

즉, 필드 주입을 사용하고 있는 클래스를 테스트하려면 스프링 컨테이너를 통해 의존관계가 설정되어야 합니다. 만약, 필드 주입을 사용하는데 스프링 컨테이너를 사용하지 않는다면 Null Pointer Exception이 발생할 것 입니다. 해당 필드에 구현체가 존재하지 않기 때문입니다.

따라서 생성자 주입을 사용하게 되면 스프링과 결합된 코드(테스트를 위해 스프링 컨테이너를 실행해야 하는 코드)가 아닌 순수한 자바 코드(스프링 컨테이너를 실행하는 게 없는 코드)로 의존관계를 주입하고 테스트를 할 수 있습니다.

.
감사합니다.

메모장님의 프로필 이미지
메모장
질문자

친절한 답변 정말 감사합니다!

그런데 제가 질문을 다소 잘못드린거같아 한번더 여쭤보고싶은게 있습니다 ㅠ

제가 질문드릴때 생각했던 테스트는 @Test를 붙이는 테스트 코드클레스를 질문드렸던거지만, 말씀주신 순수한 자바로 테스트한다고 하셨던 이부분의 테스트는 현재 의존관계가 주입받고 있는 클레스에서의 테스트를 말씀하신걸까요?

제가 헷갈리는부분은 필드주입이던 생성자주입이던 우선 어노테이션을 통해 의존관계를 주입받아 해당 빈을 가져온 상태고, 이것을 @Test가 붙은 테스트코드에서 사용하려면 결국 둘다 ApplicationContext(스프링 컨테이너)를 사용해야하기에 둘다 순수한자바 테스트가 안된다고 생각되었기 때문입니다. 

강의에서 언급하신 순수한 자바로 테스트한다는 말은 "스프링 컨텍스트"를 띄우지 않은 상태에서 하는 테스트를 말하는 것입니다.

그렇기 때문에 순수한 자바로 테스트를 진행하게 되면 필드주입은 발생하지 않습니다. 필드 주입은 스프링 컨텍스트에서 @Autowired를 감지하여 해당 필드에 들어갈 빈을 컨테이너로부터 가져와야 합니다. 그러나 스프링 컨텍스트를 사용하지 않기 때문에 필드주입이 발생하지 않습니다. 마찬가지로 생성자 주입도 "자동"으로 일어나지 않습니다.

다만, 생성자 주입의 경우 스프링 컨텍스트를 사용하여 자동으로 주입되지 않지만 수동으로 의존관계를 주입할 순 있습니다. 직접 구현체를 생성하고 생성된 구현체를 생성자에 전달하면 되니깐요.

메모장님의 프로필 이미지
메모장
질문자

답변 감사합니다. 말씀주신걸 제가 이해한바로는 결국 필드주입은 스프링 컨텍스트를 의존해야 주입받을수있어서 순수자바로 테스트를 못하지만, 생성자 주입의 경우 현재 강의의 초기내용처럼 AppConfig를 통해 주입을 받아 테스트를 할수있기때문에 순수자바로 테스트를 했다고 볼수있다. 

라고 이해했습니다. 맞을까요?

꼭 AppConfig가 아니더라도 됩니다. 의존관계에 필요한 객체를 생성해서 생성자의 파라미터로 넘겨주기만 하면 됩니다. 나머진 이해하신 부분이 맞습니다.

안녕하세요 저도 이와 비슷한 궁금증이 생겨 답변을 읽다가 혼란에 빠져버려서 질문드리고싶습니다.

 

순수 자바코드로 테스트한다는 것은 ApplicationContext를 사용하지 않는다는 것이고, @Autuwired도 동작하지 않고, 스프링 컨테이너가 없기때문에 Bean이라는 것도 없지 않나라는 생각이 들었습니다.

 

BeforeEach를 통해서 AppConfig를 이용해 MemberService, OrderService 객체를 생성하고 있습니다.

AppConfig에서는 각 메소드에 @Bean어노테이션이 붙어있고 클래스에도 @Configuration이 붙어있는데 이 어노테이션들도 순수 자바코드로 테스트할 때는 전혀 동작하지 않는 어노테이션인가요?

 

다시 한번 정리해보자면

순수 자바코드 테스트 에서는 ApplicationContext를 사용하지 않는다.

-> 스프링 컨테이너가 없다.

-> Bean을 관리하지 않는다.

-> @Autowired 포함 @Bean, @Configuration도 동작하지 않는다.

 

맞을까요..?

네, 맞습니다.

메모장님의 프로필 이미지
메모장

작성한 질문수

질문하기