Search

[springboot] 단위테스트(unit test)에서의 의존성 주입(DI)

타입
스터디
태그
springboot
상태
Published
생성일
2023/02/21 02:02
최종 편집 일시
2023/07/18 01:46
2 more properties

의존성 주입(DI ; Dependency Injection) 이란?

A 객체에서 B 객체를 사용할 때, A 객체 내부에서 B 객체를 직접 생성하지 않고 외부에서 B 객체를 주입받는 것을 의존성 주입 이라고 한다.

단위테스트(unit test) 에서도 의존성 주입을 하는 이유

단위테스트의 각 메서드가 쓰는 객체와, 테스트 대상인 레이어 로직(ex. 컨트롤러, 서비스, 레포지토리) 이 쓰는 객체가 동일함을 보장받아야 한다.
테스트 코드에서 테스트 대상 레이어에 의존성 주입을 하게 되면 같은 인스턴스를 사용함을 보장받는다.
아래 코드 예시를 보자.

코드 예시

MemberRepository.java : Member 리포지토리에 관한 추상클래스 (인터페이스)
MemoryMemberRepository.java : MemberRepository 의 구현클래스
MemberService.java : MemoryMemberRepository 객체를 사용해서 비즈니스 로직을 다루는 서비스 단 코드
MemberServiceTest.java : MemberService 의 테스트코드

의존성 주입 안 한 코드 (안 좋은 예시)

MemoryMemberRepository.java
public class MemoryMemberRepository implements MemberRepository { private static Map<Long, Member> store = new HashMap<>(); // 생략 .. }
Java
복사
MemberService.java
public class MemberService { private final MemberRepository memberRepository = new MemoryMemberRepository(); // 생략.. }
Java
복사
️ MemberService 객체 내부에서 MemoryMemberRepository 객체를 new 로 직접 만들어서 사용함
MemberServiceTest.java
class MemberServiceTest { MemoryMemberRepository memberRepository = new MemoryMemberRepository(); MemberService memberService = new MemberService(); // 생략 .. }
Java
복사
️ MemberServiceTest 에서 MemoryMemberRepository, MemberService 객체를 새롭게 만들어서 사용함

문제점

이 상황에서 MemberServiceTest를 실행시키면 MemoryMemberRepository 인스턴스가 두 개 생기는 문제가 생긴다.
1.
MemberServiceTest 내 에서의 MemoryMemberRepository 인스턴스
2.
MemberService 내 에서의 MemoryMemberRepository 인스턴스
MemberServiceTest 를 실행할 때 1번 객체는 테스트 내부에서 사용되고, 2번 객체는 MemberService 내에서 서비스 로직을 수행한다.
이는 서로 다른 인스턴스를 사용하고 있는 것이다.
하지만 테스트 상에서는 같은 객체가 사용되어야 한다.
즉, MemoryMemberRepository 인스턴스는 하나만 생성되어야 하는데 현재는 그렇지 못한 것이다.
이 문제를 의존성 주입으로 해결할 수 있다.

의존성 주입을 한 코드 (좋은 예시)

MemberService.java
@Service public class MemberService { private final MemberRepository memberRepository; @Autowired // MemberService 객체를 생성할 때, memberRepository 의존성 주입 public MemberService(MemberRepository memberRepository) { this.memberRepository = memberRepository; } // 생략.. }
Java
복사
 생성자를 통해 외부에서 memberRepository 를 주입받는다
MemberServiceTest.java
class MemberServiceTest { MemoryMemberRepository memberRepository; MemberService memberService; @BeforeEach public void beforeEach() { memberRepository = new MemoryMemberRepository(); memberService = new MemberService(memberRepository); } // 생략.. }
Java
복사
 @BeforeEach : 모든 테스트 메서드들 실행 전에 해당 메서드가 실행되도록 하는 어노테이션
 MemberServiceTest 내부에서 MemoryMemberRepository 를 생성한 다음, MemberService 를 생성할 때 인자로 MemoryMemberRepository 를 넘겨줌으로써 MemberService 객체에 MemoryMemberRepository 객체를 주입한다.
단위 테스트는 스프링 컨테이너를 띄우는 테스트(통합테스트; @SpringBootTest) 가 아니므로 스프링 빈을 이용하지 못한다. 따라서 수동으로 의존성 주입을 시켜줘야 한다.