[Spring/Test] MockHttpServletResponse body가 empty (null일 때)

Woolly·2023년 9월 8일
1

테스트 코드를 작성하다가 만나게 된 난감한 문제 중 하나

기존의 코드로 테스트를 실행할 경우
분명히 테스트도 통과했다고 뜨고, 상태 코드도 200을 반환하는데
Body의 값이 텅 비어있는 경우가 발생했다.

그렇다고 오류가 발생한 것도 아니었는데 문제는
MockMVC 중 Json Response 검증하는 JsonPath()를 사용할 때이다.

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

사실 나는 나는 jsonPath()를 통해 응답 Response 중 message의 값이 일치하는지를 추가로 검증하고 싶었는데

.andExpect(MockMvcResultMatchers.jsonPath("$.message").value("로그인에 성공하였습니다."));

이 코드를 추가하고, 테스트를 다시 실행하면 이와 같은 에러를 만나게 된다.

java.lang.AssertionError: No value at JSON path "$.message"

	at org.springframework.test.util.JsonPathExpectationsHelper.evaluateJsonPath(JsonPathExpectationsHelper.java:304)
	at org.springframework.test.util.JsonPathExpectationsHelper.assertValue(JsonPathExpectationsHelper.java:99)
	at org.springframework.test.web.servlet.result.JsonPathResultMatchers.lambda$value$2(JsonPathResultMatchers.java:111)
	at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:214)
	at com.zipkimi.user.controller.UserLoginControllerTest.loginSuccessTest(UserLoginControllerTest.java:137)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at ... (생략)

그래서 다시 찾아본 결과

기존의 when절 메서드에서 수정이 필요했다!

when(userLoginService.login(request)).thenReturn(successResponse);
  • userLoginService의 login 메서드 호출
  • request 모의 객체를 매개변수로 넘겨주고
  • successResponse라는 응답을 반환

이러한 흐름의 코드이다.

해결 방법
이 코드의 login 메서드에 전달하는 인자를 any()로 변경하는 것이다.

when(userLoginService.login(any(UserLoginRequest.class))).thenReturn(successResponse);

어떠한 객체도 처리할 수 있도록 any()를 통해, 어떤 요청이 들어가든 successResponse를 반환해줄 것이다.

TokenResponse successResponse = TokenResponse.builder().message("로그인에 성공하였습니다.").build();

수정 후 다시 테스트를 실행해보면 다음과 같이 통과하는 것을 확인할 수 있다.

MockHttpServletResponse:
           Status = 200
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", Content-Type:"application/json;charset=UTF-8", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
     Content type = application/json;charset=UTF-8
             Body = {"message":"로그인에 성공하였습니다."}
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

원인은 테스트에서 의도한 대로 이 부분의 객체가 같은 것으로 인식되지 않고 서로 다른 두 개의 객체로 인식을 해서인듯 하다.

when(userLoginService.login(request)).thenReturn(successResponse);

출처 : https://stackoverflow.com/questions/62560356/spring-boot-mockmvctest-mockhttpservletresponse-always-returns-empty-body

출처 : https://stackoverflow.com/questions/65157415/mockmvc-jsonpath-response-has-empty-body

profile
Ad Astra

0개의 댓글