본문 바로가기

Spring

@Mock vs @MockBean

MockMvc로 테스트를 하다가 @Mock과 @MockBean의 차이가 뭔지 궁금해졌다. 비슷하게 생긴 두 어노테이션은 엄연히 용도가 다르다. 간단하게 정리해보자.

@Mock

어노테이션 단어 그대로 Mock 객체, 즉 가짜 객체로 쓰겠다는 뜻이다.

@ExtendWith(MockitoExtension.class)
class ServiceTest {

    private Service service;

    @Mock
    private Repository Repository;

    @BeforeEach
    void setUp() {
        service = new Service(repository);
    }

  @Test
  void findAll() {
      given(repository.findAll()).willReturn(...);
      List<String> actual = service.findAll();
      ...
  }

가짜 repository로 Serivce객체를 생성해서 협력 객체인 repository의 값을 지정해줘서 service 로직만을 테스트했다. 단순히 가짜 객체를 만들어서 값을 지정해주고 싶다면 @Mock 어노테이션을 쓰면 된다.

@MockBean

MockBean 또한 어노테이션 단어 뜻 그대로 Mock Bean, 즉 가짜 Bean을 만들겠다는 뜻이다.

@WebMvcTest(controllers = Controller.class)
@AutoConfigureMockMvc
class ContollerTest {

    private MockMvc mockMvc;

    @MockBean
    private Service service;

    @BeforeEach
    void setUp(WebApplicationContext webApplicationContext) {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
                .addFilter(new CharacterEncodingFilter("UTF-8", true))
                .build();
    }

    @Test
    void findAll() {
         given(service.findAll()).willReturn(...);
         mockMvc.perform(get("/")
                .accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk()))
                ...

    }
}

실제 요청을 하고 Service에는 지정된 값을 줘서 Controller 로직을 테스트했다.

@WebMvcTest 이기 때문에 Controller까지는 로드 된다. 하지만 Controller의 협력 객체인 Service는 로드되지 않는다.

그래서 contoller에 실제로 요청을 보낼 때 controller의 협력 객체인 service가 Bean Container에 생성되어 있지 않다면 NPE가 터진다.

이 처럼 @MockBean은 Bean Container에 생성돼야만 하는 가짜 객체일 때 사용하면 된다.

'Spring' 카테고리의 다른 글

DDD에서는 왜 간접 참조를 더 권장할까?  (0) 2020.10.10
WebMvcConfigurer addResourceHandlers 경로 설정  (0) 2020.09.12
MockMvc VS RestAssured  (0) 2020.08.14
Tacademy JPA 강의 정리  (1) 2020.07.01
용어 정리  (0) 2020.04.21