또 google로 들어갔을 때 Tistory not found가 뜬다 그래서 bing으로 들어기 글을 쓰게 되었다 ,,,
앞서서 단위테스팅과, 기본 @Springboottest를 통하여 간단한 API계층 테스트를 알아 보았다,
이제는 Mockito를 사용하여 가짜 Mock을 통해서 가짜 의존성을 주입해 주는 것을 통한 테스팅을 해볼 것 이고, 이를 통해서 API document까지 한번에 작성하는 spring restdocs까지 알아볼 것이다.
만약 membercontroller에서 member에 정보를 저장하는 createMember의 메서드의 기능을 테스트하고 싶다고 했을 때
@WebMvcTest
@AutoConfigureMockMvc
class MemberControllerMockTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private Gson gson;
// (1)
@MockBean
private MemberService memberService;
// (2)
@Autowired
private MemberMapper mapper;
@Test
void postMemberTest() throws Exception {
MemberDto.Post post = new MemberDto.Post("hgd@gmail.com",
"홍길동",
"010-1234-5678");
Member member = mapper.memberPostToMember(post);
member.setMemberId(1L);
given(memberService.createMember(Mockito.any(Member.class)))
.willReturn(member);
String content = gson.toJson(post);
ResultActions actions =
mockMvc.perform(
post(//"uri")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
// then
actions
.andExpect(status().isCreated());
}
}
이런 형식으로 테스트를 할 수 있다. 코드를 간략하게 설명해 보자면,
1: 실제 controller에서 사용하는 memberservice에 대한 의존성을 가져오고 그 다음 repository로 가는 의존성을 끊기 위해서 MockBean을 통해서 의존성을 주입해준다.
2:
given(memberService.createMember(Mockito.any(Member.class)))
.willReturn(member);
given이라는 명령어를 통해서 member란 객체를 미리 만들어 놓고, memberService를 통해서 받아 올 거라고 속여준다. 여기서 Mockito를 사용하게 된다.
ResultActions actions =
mockMvc.perform(
post(//"uri")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
);
// then
actions
.andExpect(status().isCreated());
Controller의 uri로 mockMvc를 통해서 보내주고, 불러들인 결과를 통해서 test를 하면 끝이다.
actions.andDo(
MockMvcResultHandlers.print()
)
이 코드를 통해서 모든 결과 값을 받아 올 수있다.
이제 이런 sliding test를 통해서 api 문서화를 할 수 있는데 , Spring rest docs를 사용할 것이고, build하는 부분은 생략하겠다.
.andDo(document( // (7)
"post-member", // (7-1)
getRequestPreProcessor(), // (7-2)
getResponsePreProcessor(), // (7-3)
requestFields( // (7-4)
List.of(
fieldWithPath("email").type(JsonFieldType.STRING).description("이메일"), // (7-5)
fieldWithPath("name").type(JsonFieldType.STRING).description("이름"),
fieldWithPath("phone").type(JsonFieldType.STRING).description("휴대폰 번호")
)
),
responseHeaders( // (7-6)
headerWithName(HttpHeaders.LOCATION).description("Location header. 등록된 리소스의 URI")
)
));
코드를 간략하게 설명하자면 이런 형식입니다.
andDo(document를 통해 rest docs를 작성할 것이라는 선언을하고, 이름을 명시하고,
requestFields라는 이름과 타입과 설명을 지정합니다.
마찬가지로 아래도 responseheader라는 이름과 이름과 설명을 지정합니다.
getRequestPreProcessor(),
이 메서드는 아래와 같은 명령의 반환 타입을 가집니다.
return preprocessRequest(prettyPrint());