강의

멘토링

로드맵

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

3831568님의 프로필 이미지
3831568

작성한 질문수

토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1

MemberRegisterTest에서 @SpringBootTest 질문

해결된 질문

작성

·

63

0

MemberRegisterTest를 진행할 때 @SpringBootTest를 사용해서 테스트를 진행했는데요

서비스 테스트에는 @ExtendWith(MockitoExtension.class)를 사용하는 경우를 많이 봤습니다

 

헥사고날 아키텍처에서는 애플리케이션과 도메인이 중심이 되기 때문에 서비스에서 @SpringBootTest를 사용한걸까요?

답변 1

1

토비님의 프로필 이미지
토비
지식공유자

그건 아닙니다. 테스트 작성과 수행에 유리하기 때문에 선택한 방법입니다.

Repository나 EmailSender와 같은 기능 요구 인터페이스를 이용하는 애플리케이션의 내의 코드를 테스트하려면 실제 그 인터페이스 타입의 동작하는 오브젝트가 필요합니다. 그러려면 이 인터페이스를 구현한 클래스가 필요한데, 이걸 실제 어댑터 클래스를 가져다 쓰면 테스트에서도 환경에 종속이 되버릴 수가 있습니다. 그래서 테스트를 위해서 이 인터페이스를 구현한, 테스트 더블(대역) 오브젝트를 생성해야 하죠.

이때 사용하는 방식이 스텁, 목 같은 것입니다. 제가 애플리케이션 서비스 테스트를 만드는 방법을 여러가지 보여드렸는데, 가장 단순하게는 테스트 내에 그 인터페이스를 구현한 스텁이나 목 기능을 가진 클래스를 직접 만드는 것입니다. 명확하고 쉽긴 하지만 인터페이스의 기능이 많아지면 테스트를 위해서 많은 양의 코드를 작성해야 합니다. 심지어는 테스트 코드보다도 더 많은 양이 필요하죠.

그래서 특별한 경우를 제외하면 기능 요구 인터페이스의 테스트용 오브젝트는 말씀하신 Mockito 같은 손쉬운 목/스텁 오브젝트 생성 프레임워크의 도움을 받습니다. 리포지토리도 JPA를 사용했을 때 주고 받을 정보를 가정해서 그걸로 목 오브젝트를 설정할 수 있습니다.

문제는 리포지토리처럼 DB를 다루는 인터페이스는 스텁으로 넣어줘야 할 정보가 꽤 많습니다. 엔티티가 점점 커지고 조회할 정보가 많아지면 그걸 매번 Mockio 등으로 세팅하는 것도 제법 큰 일입니다. 그런데다가 등록 후에 조회와 같이 정확하게 DB처럼 동작해야 로직이 바르게 수행되고, 그래야 최종 테스트가 의미있는 상황을 만들려면 꽤나 손이 많이 갑니다.

그래서 이런 경우 스프링에서 권장하는 방식은 목 대신 페이크 오브젝트를 이용하는 것인데, 여기서는 메모리 DB(H2)를 실제 DB 대신 사용하는 가상의 기능을 수행하는 오브젝트로 쓰는 것이죠. 거기에 Spring Data가 지원해주는 리포지토리 구현 자동화까지 결합하면, 실제 운영에서 쓸 DB는 아니지만 그와 거의 유사한 방식으로 동작하는 DB까지 동작하게 해서 테스트를 만들 수 있습니다. 이게 주는 장점이 많기 때문에 스프링/부트에서도 핵심 테스트 기능으로 지원합니다.

DB와 관련 작업을 Mockito로 대체해서 만들어서 테스트하는 방식으로는 JPA의 모델이 바르게 설정되어있는지에 대한 검증이 안 되기 때문에, 이건 또 DB까지 연결하는 방식의 테스트를 따로 만들어야 하고, 이게 테스트마다 동일한 방식으로 셋업되고 동작하게 하려면 매우 큰 수고가 필요합니다.

테스트를 만드는 비용이 증가하고 시간이 많이 걸리면, 자연스럽게 테스트를 안 만들게 됩니다. 그래서 저는 JPA를 사용하는 경우 메모리 DB를 이용한 스프링의 테스트 지원 기능을 적극적으로 사용합니다. 그렇게 해도 충분히 도메인과 애플리케이션 서비스 로직에 충실한 테스트를 만들 수 있습니다.

그 외의 특별한 겻우라면 Mockito을 활용한 테스트를 사용할 수 있습니다. 다만, Mockito를 쓰는 경우에 목 오브젝트를 동적으로 만들려면 테스트 진행에 부하가 걸립니다. 그래서 테스트 실행 속도에 영햣을 주기도 합니다. Mickto와 Spring Test의 Mockito 관련 문서를 잘 보고, 성능에 영향을 최소한으로 주도록 하는 방법을 살펴보는 것이 중요합니다.

3831568님의 프로필 이미지
3831568

작성한 질문수

질문하기