# 오류
spring-restdocs를 사용하여 API문서를 자동화하고자 테스트케이스를 개발하고 있었다.
공식가이드와 블로그를 참고하여 개발하였는데 아래와 같은 오류가 계속 발생했고 실행 후에 계속 request-fields.adoc 파일의 내용이 비어있었다.
Cannot handle application/x-www-form-urlencoded;charset=UTF-8 content as it could not be parsed as JSON or XML
org.springframework.restdocs.payload.PayloadHandlingException: Cannot handle application/x-www-form-urlencoded;charset=UTF-8 content as it could not be parsed as JSON or XML
# 원인
위의 에러가 발생하는 기존 소스코드는 아래와 같다.
Map param = new HashMap<>(); // (1)
param.put("category", "callback" );
param.put("comment", "comment" );
param.put("context", "context" );
ResultActions result = this.mockMvc.perform(
post("/lc/actionLog/writeLog")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(convertMapToQueryString(param)) // (2)
);
//then
result.andDo(document("write-actionlog", requestFields( // (3)
fieldWithPath("category").description("Category 카테고리"),
fieldWithPath("comment").description("Comment 코멘트"),
fieldWithPath("context").description("Context 컨텍스트")
), ...
위 소스코드에 구현된 API의 스펙은 다음과 같다.
POST /lc/actionLog/writeLog HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
해당 API로 Map 객체를 쿼리스트링 형태로 변환해서 content() 함수 인자로 넣어 전송했다. ...... (1), (2)
문서화 하는 부분은 requestFields함수에 FieldDescriptor[] 객체로 코드를 작성했다. ...... (3)
요청하는 API는 x-www-form-urlencoded 컨텐츠타입으로 파라미터를 전송하는 API인데
json 또는 xml 형태의 데이터를 사용 및 문서화하는 content()와 requestFields() 메소드를 사용했기 때문에 발생하는 오류인 것 같았다.
이를 수정하려면 Map을 쿼리스트링으로 바꾸는게 아니라 사용하는 함수를 바꿔야 했다.
# 해결
변경할 부분은 다음과 같다. (As-Is ▶ To-Be)
(1) Map param ▶ 삭제
(2) content(param) ▶ param("k", "v")
(3) requestFields() ▶ requestParameters ()
(4) fieldWithPath() ▶ parameterWithName()
수정된 소스코드는 다음과 같다.
ResultActions result = this.mockMvc.perform(
post("/lc/actionLog/writeLog")
.param("category", "callback" ) // (2)
.param("comment", "comment" )
.param("context", "context" )
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
);
//then
result.andDo(document("write-actionlog",
requestParameters( // (3)
parameterWithName("category").description("Category 카테고리"), // (4)
parameterWithName("comment").description("Comment 코멘트"),
parameterWithName("context").description("Context 컨텍스트")
...