생계유지형 개발자/Stack Over Flow 한국판

spring-restdocs로 API문서 자동화 실행 시 it could not be parsed as JSON or XML 발생

이 가을 2020. 6. 24. 18:08

# 오류

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 컨텍스트")
        ...