반응형
1. 문제
JUnit test에서 MockMvc를 사용해 POST API를 호출할 때 JSON content를 API에서 제대로 Parsing 하지 못해 HttpMessageNotReadableException이 발생할 수 있다.
Test
@Test
public void testPost() throws Exception{
//language=JSON
String json = "{\n" +
" \"title\" : \"Greetings\",\n" +
" \"value\" : \"Hello World\"\n" +
"}\n";
mockMvc.perform(
post("/hello/post")
.contentType(MediaType.APPLICATION_JSON)
.content(json))
.andExpect(status().isOk())
.andExpect(jsonPath("$.title", Matchers.is("Greetings")))
.andExpect(jsonPath("$.value", Matchers.is("Hello World")))
.andExpect(jsonPath("$.*", Matchers.hasSize(2)));
}
API
@PostMapping(value ="/post", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public Hello post(@RequestBody Hello hello){
return hello;
}
따라서 아래와 같이 400 ERROR를 return 한다.
2. 원인
API에서 @RequestBody로 전달받을 객체로 사용한 Hello의 접근제한자가 문제였다. 간단히 Hello를 private로 API를 작성한 Controller 내부에 선언해놨었는데, 이 때문에 HttpServlet이 JSON 메세지를 Hello 객체라고 인식하지 못했다.
전체 Controller 코드는 아래와 같다.
HelloResource
@RestController
@RequestMapping("/hello")
public class HelloResource {
@PostMapping(value ="/post", consumes = MediaType.APPLICATION_JSON_VALUE
, produces = MediaType.APPLICATION_JSON_VALUE)
public Hello post(@RequestBody Hello hello){
return hello;
}
private class Hello {
private String title;
private String value;
public Hello(){
}
public Hello(String title, String value) {
this.title = title;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
}
}
3. 해결
private으로 선언한 Hello class를 public static으로 변경하면 된다. 변경 후 테스트하면 아래와 같이 테스트가 정상적으로 통과한다.
HelloResource
@RestController
@RequestMapping("/hello")
public class HelloResource {
@PostMapping(value ="/post", consumes = MediaType.APPLICATION_JSON_VALUE
, produces = MediaType.APPLICATION_JSON_VALUE)
public Hello post(@RequestBody Hello hello){
return hello;
}
public static class Hello {
private String title;
private String value;
public Hello(){
}
public Hello(String title, String value) {
this.title = title;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getTitle(){
return title;
}
public void setTitle(String title){
this.title = title;
}
}
}
추천서적
파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
반응형