본문 바로가기
스터디/Spring

[Spring] 스프링 @MockBean, @SpyBean

by zoodi 2023. 3. 12.
728x90

배경

스프링과 Junit을 이용해서 테스트 코드를 작성하다 보면 테스트 환경(database, api)을 구현하는 코드까지 작성해야 하고 실제 테스트할 코드보다 환경을 구현하는 코드가 훨씬 더 복잡해지게 됩니다.

이런 문제 영역을 해결하기 위해서 테스트 더블 이라는 것이 나왔고 Java진영에서는 대표적으로 Mockito가 있습니다.

Mockito를 사용하다보면 아래 어노테이션을 자주 접하게됩니다.

 

 

@Mock
@MockBean
@Spy
@SpyBean
@InjectMocks

 

SpringBoot 1.4에서 2개의 테스트 어노테이션 @MockBean, @SpyBean 이 추가되었습니다.

 

두 어노테이션 모두 spring-boot-test에서 제공하는 어노테이션입니다.

 

Spring 에서는 보통 객체생성시 직접 생성하지 않고 Dependency Injection(DI)을 통해 프레임워크에 위임하여 생성하기 때문에 직접적으로 Mocking 테스트환경을 만드는것이 쉽지 않습니다.

 

이러한 어려움을 도와주는것이 바로 @MockBean과 @SpyBean입니다.

기본적인 개념은 조금 다르나 사용법은 @MockBean @SpyBean은 동일합니다.

 

@MockBean

@Mock 과 비슷한 @MockBean이라는 어노테이션이 있습니다. 이름이 비슷한것처럼 실제로도 비슷하게 동작합니다.

하지만 @Mockbean은 경로(org.springframework.boot.test.mock.mockito.MockBean)를 봐도 알 수 있듯이 @Mock과는 다르게 spring 영역에 있는 어노테이션이라는 것을 알 수 있습니다.

@Mock과 달리 spring-boot-test에서 제공하는 어노테이션이고 Spring이 관리하는 bean들 중에서 하나 이상을 mock 객체로 사용하고 싶을 때 사용합니다.

@MockBean은 스프링 컨텍스트에 mock객체를 등록하게 되고 스프링 컨텍스트에 의해 @Autowired가 동작할 때 등록된 mock객체를 사용할 수 있도록 동작합니다.

@MockBean은 given에서 선언한 코드 외에는 전부 사용할 수 없습니다.

 

@Mock과 @MockBean의 차이가 헷갈릴 수 있는데요 정리하자면 아래와 같습니다.

Mock 종류의존성 주입 Target

Mock 종류 의존성 주입 Target
@Mock @InjectMocks
@MockBean @SpringBootTest

- @Mock은 @InjectMocks에 대해서만 해당 클래스안에서 정의된 객체를 찾아서 의존성을 해결합니다.

- @MockBean은 mock 객체를 스프링 컨텍스트에 등록하는 것이기 때문에 @SpringBootTest를 통해서 Autowired에 의존성이 주입되게 됩니다.

 

@SpyBean

가짜 객체를 만들어서 stub을 해주는 @MockBean과 달리, @SpyBean은 given에서 stub한 메서드 외에는 그 객체의 실제 메서드를 사용할 수 있습니다.

(*stub: 기대 행위를 작성하는 것)

 

@Spybean은 given에서 선언한 코드 외에는 전부 실제 객체의 것을 사용합니다.

마치 실제 객체의 메서드들 중에서 우리가 지정한 특정 메서드만 의도대로 작동되게 하는 것이 그 객체에 스파이를 하나 심어둔 것 같다고 생각하면 이해하기 쉽습니다.

특정 객체의 일부 메서드만 stub하고, 나머지는 실제 메서드를 사용하고 싶을 때 @SpyBean을 사용합니다.

 

@SpyBean은 실제 구현된 객체를 감싸는 프록시 형태이기 때문에 스프링 컨텍스트에 실제 구현체가 등록되어있어야 합니다.

 

출처

https://github.com/mockito/mockito/wiki/Mockito-features-in-Korean

https://jojoldu.tistory.com/226

728x90

댓글