자바 스프링부트로 테스트 코드를 짜던 중 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을 사용해주어야하는 것 같다.
참고자료
액션플랜
다음에는 SpyBean 과 MockBean의 차이를 알아보자
'개발 관련 학습 및 문제해결' 카테고리의 다른 글
PATCH 로 객체 수정 후에도 프론트에서 즉시 반영이 안되는 현상/동기 비동기처리 [20221126-TIL] (0) | 2022.11.26 |
---|---|
useEffect 무한 렌더링 문제, forceUpdate 후에도 계속 이전 텍스트가 화면에 남는 문제 [20221125 -TIL] (0) | 2022.11.25 |
TDD, 리액트 프론트엔드 테스트 코드 범위 정하기[20221123-TIL] (0) | 2022.11.23 |
깃 용어 이것만 알면된다! 기초 완벽 정리[20221122-TIL] (0) | 2022.11.22 |
반드시 한 것은 남기자[스프린트 5주차 주간회고] (0) | 2022.11.21 |
댓글