본문 바로가기
개발 관련 학습 및 문제해결

@Mock과 @MockBean의 차이는 뭘까?

by 날파리1 2022. 11. 24.

자바 스프링부트로 테스트 코드를 짜던 중 Mock 어노테이션과 MockBean어노테이션이 있어 어떤 것을 이용해야하나 고민을 하다 둘의 차이가 궁금해졌다.

 

@Mock  과 mock(*.class)

그리고 Mock어노테이션과 mock(*.class)의 차이도 궁금했는데 이는 방법의 차이라고한다.

 

1. 어노테이션

테스트할 곳에서 

필드화 시켜놓은 곳에서 @Mock 을 선언해준다.

 

@Mock

private PostRepository postRespository

 

2. mock( )

PostRepository postRepository = mock(PostRepository.class);

 

@MockBean이란?

@MockBean은 스프링 부트 테스트에서 제공하는 어노테이션이다.

@MockBean은 스프링 컨텍스트에 mock객체를 등록하고 스프링 컨텍스트에 의해 @Autowired가 동작할 때 등록된 mock객체를 사용할 수 있도록 동작한다고 한다. 또한 @MockBean은 mock 객체를 스프링 컨텍스트에 등록하기 때문에 @SpringBootTest를 통해서 Autowired에 의존성이 주입한다.

 

적용

사실 위 처럼 말하면 잘 와닿지 않는데 다음은 실사용예제를 담았다.

@Mock은 서비스테스트 단위에서 레포지토리를 모킹해올 때 주로 거의 사용했다. 

레포지토리도 의존성 주입을 위해 서비스단의 생성자에 매개변수로 넣어주는데 테스트는 @Mock을 사용했다.

 

서비스에서 레포지토리를 모킹해올때 아래와 같이 사용했다.

class CreateGrammarServiceTest {
  private GrammarRepository grammarRepository;
  private CreateGrammarService createGrammarService;

  @BeforeEach
  void setUp() {
    grammarRepository = mock(GrammarRepository.class);

    createGrammarService = new CreateGrammarService(grammarRepository);
  }

  @Test
  void createGrammar() {

    given(grammarRepository.save(any())).willReturn(
        Grammar.fake()
    );

    GrammarDto grammarDto = createGrammarService.grammar(GrammarDto.fake());

    verify(grammarRepository).save(any());

    assertThat(grammarDto.getIntroduction()).isEqualTo("grammar introduction");
  }
}

 

반대로 

@MockBean은 컨트롤러에서 서비스를 모킹해오는데 사용했다.

 

관리자 페이지의 문법이란 도메인을 post 하는 controller 테스트에서 아래와 같이 사용했다.

 

@WebMvcTest(GrammarAdminController.class)
class GrammarAdminControllerTest {
  @Autowired
  private MockMvc mockMvc;

  @MockBean
  private CreateGrammarService createGrammarService;

  @BeforeEach
  void setUp() {

  }

  @Test
  void createGrammar() throws Exception {

    given(createGrammarService.grammar(GrammarDto.fake()))
        .willReturn(Grammar.fake().toDto());

    mockMvc.perform(MockMvcRequestBuilders.post("/admin/grammar")
            .contentType(MediaType.APPLICATION_JSON)
            .content("{" +
                "\"introduction\":\"grammar introduction\"," +
                " \"content\":\"this is content\"" +
                "}"))
        .andExpect(status().isCreated());

    verify(createGrammarService).grammar(any());
  }
}

 

컨트롤러 단위에서 @MockBean을 @Mock으로 수정하여 테스트를 시행하니 아래와 같이 오류를 내뱉는다.

테스트할 컨트롤러의 이름으로 빈 생성을 실패했다는 오류인 것 같다.

 

요약하면 서비스 테스트에서 레포지토리를 모킹해올때는 @Mock 을 빈 주입을 요구하는 컨트롤러 테스트에서는 스프링 부트 테스트에서 제공하는 @MockBean을 사용해주어야하는 것 같다.

 

 

참고자료

 

Mockito @Mock @MockBean @Spy @SpyBean 차이점

예제 코드 https://github.com/cobiyu/MockitoSample Test Double이 왜 필요한 지부터 시작하는 기본적인 테스트 코드부터 한 단계씩 발전시켜나가며 Mockito의 어노테이션들의 정확한 쓰임새에 대해 살펴보겠습

cobbybb.tistory.com

 

 

[SpringBoot] @Mock, @MockBean 차이가 뭘까?

테스트 케이스를 작성하다가 좀 헷갈리는게 있었다. @Mock, @MockBean 차이가 뭐지??? 쓰긴 하고 있는데 알고 써야 하지 않을까라는 의문이 들었다. 그래서 찾아봤다. 먼저 Mock 객체를 선언할 때에는 2

blusky10.tistory.com

 

액션플랜

다음에는 SpyBean 과 MockBean의 차이를 알아보자

댓글