Test코드 작성하는 과제를 하다가 controller테스트를 만들면서 막히게 되었다.
다음과 같은 테스트 코드를 실행했는데
@Test
@DisplayName("회원가입 컨트롤러 테스트")
void signup() throws Exception {
//given
MultiValueMap<String, String> signupRequestForm = new LinkedMultiValueMap<>();
signupRequestForm.add("username","sparta");
signupRequestForm.add("password","codingClub");
//when-then
mvc.perform(post("/api/signup")
.params(signupRequestForm)
)
.andDo(print());
}
아래와 같이 HttpMessageNotReadableException 예외가 생기면서 MockHttpServletResponse의 상태가 400이고 아무값도 담기지 않게 되었다.
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/signup
Parameters = {username=[sparta], password=[codingClub]}
Headers = []
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.sparta.springtodoapp.controller.UserController
Method = com.sparta.springtodoapp.controller.UserController#signup(UserRequestDto)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotReadableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 400
Error message = null
Headers = []
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
> Task :test
converter.HttpMessageNotReadableException에 대해서 찾아보니 대충 json 형태가 아니라서 그렇다고 한다.
처음에는 반환 값이 문제인 줄 알고 계속 반환 값이 왜 문제지만 생각하면서 강의 내용과 비교하던 중 강의에서는 컨트롤러 부분에서 파라미터를 받을 때 @RequestBody로 받는 것이 아니라 @ModelAttribute 방식으로 받고 있었다.
위 테스트 코드에서처럼 params으로 넘겨주게 되면 @RequestBody 형식은 json 형식으로 변환을 못하는 것 같다.

위 코드를 아래처럼 바꿔 ModelAttribute방식(생략 가능)으로 하니 해결되었다.

MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/signup
Parameters = {username=[sparta], password=[codingClub]}
Headers = []
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = com.sparta.springtodoapp.controller.UserController
Method = com.sparta.springtodoapp.controller.UserController#signup(UserRequestDto)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 201
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"message":"회원가입 성공","status":201}
Forwarded URL = null
Redirected URL = null
Cookies = []
> Task :test
🎈ModelAttribute를 저번에 대충 공부하고 넘겼었는데 ModelAttribute방식을 사용하려면 해당 객체에 데이터를 바인딩할 수 있는 생성자를 만들거나 setter를 설정해야 사용 가능하다