getActions
.andExpect(status().isOk())
.andDo(
document(
"get-members",
getRequestPreProcessor(),
getResponsePreProcessor(),
requestParameters(
List.of(
parameterWithName("page").description("페이지 번호"),
parameterWithName("size").description("페이지 사이즈")
)),
responseFields(
List.of(
fieldWithPath("data").type(JsonFieldType.OBJECT).description("결과 데이터"),
fieldWithPath("data[].memberId").type(JsonFieldType.NUMBER).description("회원 식별자"),
fieldWithPath("data[].name").type(JsonFieldType.STRING).description("이름"),
fieldWithPath("data[].phone").type(JsonFieldType.STRING).description("휴대폰 번호"),
fieldWithPath("data[].email").type(JsonFieldType.STRING).description("이메일"),
fieldWithPath("data[].memberStatus").type(JsonFieldType.STRING).description("회원 상태: MEMBER_ACTIVE(활동중) / MEMBER_SLEEP(휴면 계정) / MEMBER_QUIT(탈퇴)"),
fieldWithPath("data[].stamp").type(JsonFieldType.NUMBER).description("스탬프 갯수")
)
)
)
);
getActions
.andExpect(status().isOk())
.andDo(
document(
"get-members",
getRequestPreProcessor(),
getResponsePreProcessor(),
requestParameters(
List.of(
parameterWithName("page").description("페이지 번호"),
parameterWithName("size").description("페이지 사이즈")
)),
responseFields(
List.of(
fieldWithPath("data").type(JsonFieldType.ARRAY).description("결과 데이터"),
fieldWithPath("data[].memberId").type(JsonFieldType.NUMBER).description("회원 식별자"),
fieldWithPath("data[].name").type(JsonFieldType.STRING).description("이름"),
fieldWithPath("data[].phone").type(JsonFieldType.STRING).description("휴대폰 번호"),
fieldWithPath("data[].email").type(JsonFieldType.STRING).description("이메일"),
fieldWithPath("data[].memberStatus").type(JsonFieldType.STRING).description("회원 상태: MEMBER_ACTIVE(활동중) / MEMBER_SLEEP(휴면 계정) / MEMBER_QUIT(탈퇴)"),
fieldWithPath("data[].stamp").type(JsonFieldType.NUMBER).description("스탬프 갯수"),
fieldWithPath("pageInfo").type(JsonFieldType.OBJECT).description("페이지 정보"),
fieldWithPath("pageInfo.page").type(JsonFieldType.NUMBER).description("페이지 정보"),
fieldWithPath("pageInfo.size").type(JsonFieldType.NUMBER).description("사이즈 정보"),
fieldWithPath("pageInfo.totalElements").type(JsonFieldType.NUMBER).description("전체 조회 건 수"),
fieldWithPath("pageInfo.totalPages").type(JsonFieldType.NUMBER).description("전체 페이지 수")
)
)
)
)
.andReturn();
The following parts of the payload were not documented:
{
"pageInfo" : {
"page" : 1,
"size" : 2,
"totalElements" : 2,
"totalPages" : 1
}
}
org.springframework.restdocs.snippet.SnippetException: The following parts of the payload were not documented:
{
"pageInfo" : {
"page" : 1,
"size" : 2,
"totalElements" : 2,
"totalPages" : 1
}
}
pageInfo
부분의 payload were not documented
라고 한다. pageInfo
데이터가 전송되는 과정에서 문서화가 안 되는 것이다. (문서화할 때 회원 전체 조회 하단에 페이지 정보를 제공하는 것을 목표하고 있다.)SnippetException
은 런타임 익셉션 에러 중 하나로, 스니펫 생성시 문제가 발생할 때 던져진다. (thrown to indicate a problem with the generation of a document snippet
) 따라서 스니펫 생성에 대해 자세히 알아볼 필요가 있다.
스프링 REST Docs 공식문서의 Documenting your API 부분의 Request Parameters 부분 전문이다. 여기서 SnippetException
에러와 관련 깊은 부분은 아래와 같다.
When documenting request parameters, the test will fail if an undocumented request parameter is used in the request. Similarly, the test will also fail if a documented request parameter is not found in the request.
SnippetException
가 발생한 것이다.responseFields에 pageInfo
추가fieldWithPath("pageInfo").type(JsonFieldType.OBJECT).description("페이지 정보"),
fieldWithPath("pageInfo.page").type(JsonFieldType.NUMBER).description("페이지 정보"),
fieldWithPath("pageInfo.size").type(JsonFieldType.NUMBER).description("사이즈 정보"),
fieldWithPath("pageInfo.totalElements").type(JsonFieldType.NUMBER).description("전체 조회 건 수"),
fieldWithPath("pageInfo.totalPages").type(JsonFieldType.NUMBER).description("전체 페이지 수")
.andDo(document(...))
안의 responseFields
에 pageInfo
에 해당하는 전송 데이터를 추가해주었다. 생각해보면 response에 뜨길 바라는 데이터는 애초에 넣는 것이 자연스럽긴 하다.
requestParameters(
List.of(
parameterWithName("page").description("페이지 번호").ignored(),
parameterWithName("size").description("페이지 사이즈").ignored()
)),
번외지만, 공식 문서에 나왔듯이 문서에 리퀘스트 파라미터를 드러내고 싶지 않으면 .ignored()
를 붙이면 된다고 한다.
그리고 통과된 코드의 마지막을 보면.andReturn()
이 추가 되어있다. 넣어도 빼도 테스트는 통과한다. .andReturn()
은 HTTP 통신시 주고 받는 값을 가져올 수 있는 기능으로, 사진처럼 다양한 메서드와 함께 써서 값을 변수에 바로 담아서 활용할 수 있게 해준다. (처음엔 이것만 추가하면 documentation도 처리되는줄 알았는데, 스니펫 문서화와 값을 받는 기능은 완전히 다른 동작이다.)
참고 자료