programing

mockMvc를 사용하여 응답 본문에서 문자열을 확인하는 방법

prostudy 2022. 4. 23. 10:24
반응형

mockMvc를 사용하여 응답 본문에서 문자열을 확인하는 방법

간단한 통합 테스트가 있다.

@Test
public void shouldReturnErrorMessageToAdminWhenCreatingUserWithUsedUserName() throws Exception {
    mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON)
        .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}"))
        .andDo(print())
        .andExpect(status().isBadRequest())
        .andExpect(?);
}

마지막 줄에서 응답 본문에 수신된 문자열을 예상 문자열과 비교하려고 함

이에 대한 응답으로 다음과 같은 결과를 얻었다.

MockHttpServletResponse:
          Status = 400
   Error message = null
         Headers = {Content-Type=[application/json]}
    Content type = application/json
            Body = "Username already taken"
   Forwarded URL = null
  Redirected URL = null

내용()과 본문()으로 몇 가지 재주를 부렸으나 아무 소용이 없었다.

전화할 수 있다.andReturn()그리고 반송된 것을 사용한다.MvcResult내용을 a로서 얻는 것을 반대하다.String.

아래를 참조하십시오.

MvcResult result = mockMvc.perform(post("/api/users").header("Authorization", base64ForTestUser).contentType(MediaType.APPLICATION_JSON)
            .content("{\"userName\":\"testUserDetails\",\"firstName\":\"xxx\",\"lastName\":\"xxx\",\"password\":\"xxx\"}"))
            .andDo(MockMvcResultHandlers.print())
            .andExpect(status().isBadRequest())
            .andReturn();

String content = result.getResponse().getContentAsString();
// do what you will 

@Sotirios Dividanolis 답변은 내가 이 mockMvc 주장 내에서 문자열 비교를 찾던 중 작업을 수행한다.

그래서 여기 있다.

.andExpect(content().string("\"Username already taken - please try with different username\""));

물론 내 주장은 실패한다.

java.lang.AssertionError: Response content expected:
<"Username already taken - please try with different username"> but was:<"Something gone wrong">

이유:

  MockHttpServletResponse:
            Body = "Something gone wrong"

그래서 이것은 그것이 효과가 있다는 증거다!

스프링 MockMvc는 현재 JSON에 대한 직접적인 지원을 받고 있다.그러니까 그냥 이렇게 말해라.

.andExpect(content().json("{'message':'ok'}"));

그리고 끈 비교와는 달리, 그것은 "missing field xyz"나 "message expected ok" got 'nok'과 같은 것을 말할 것이다.

이 방법은 4.1년 봄에 도입되었다.

이러한 답을 읽으면 봄 버전 4.x와 관련된 많은 것을 볼 수 있는데, 나는 다양한 이유로 버전 3.2.0을 사용하고 있다.그러니까 json 같은 것은 바로 그 자리에서 받쳐주는 겁니다.content()불가능해

나는 사용한다는 것을 알았다.MockMvcResultMatchers.jsonPath정말 쉬워서 잘 먹힌다.여기 포스트 메소드를 테스트하는 예가 있다.

이 솔루션의 이점은 완전한 json 문자열 비교에 의존하지 않고 속성에 여전히 일치한다는 것이다.

(사용)org.springframework.test.web.servlet.result.MockMvcResultMatchers)

String expectedData = "some value";
mockMvc.perform(post("/endPoint")
                .contentType(MediaType.APPLICATION_JSON)
                .content(mockRequestBodyAsString.getBytes()))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.jsonPath("$.data").value(expectedData));

요청 본문은 json 문자열에 불과했는데, 원하면 진짜 json 모의 데이터 파일에서 쉽게 로드할 수 있지만, 질문에서 이탈했을 것이기 때문에 여기에 포함시키지 않았다.

돌아온 실제 json은 다음과 같이 보였을 것이다.

{
    "data":"some value"
}

스프링의 튜토리얼에서 가져온 내용

mockMvc.perform(get("/" + userName + "/bookmarks/" 
    + this.bookmarkList.get(0).getId()))
    .andExpect(status().isOk())
    .andExpect(content().contentType(contentType))
    .andExpect(jsonPath("$.id", is(this.bookmarkList.get(0).getId().intValue())))
    .andExpect(jsonPath("$.uri", is("http://bookmark.com/1/" + userName)))
    .andExpect(jsonPath("$.description", is("A description")));

is다음에서 사용 가능import static org.hamcrest.Matchers.*;

jsonPath다음에서 사용 가능import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

그리고jsonPath참조는 여기에서 찾을 수 있다.

봄철 경비대@WithMockUser그리고 햄크레스트.containsString매처는 간단하고 우아한 솔루션을 만든다.

@Test
@WithMockUser(roles = "USER")
public void loginWithRoleUserThenExpectUserSpecificContent() throws Exception {
    mockMvc.perform(get("/index"))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("This content is only shown to users.")));
}

Github에 대한 추가 예제

여기서 더욱 우아한 방법.

mockMvc.perform(post("/retrieve?page=1&countReg=999999")
            .header("Authorization", "Bearer " + validToken))
            .andExpect(status().isOk())
            .andExpect(content().string(containsString("regCount")));

JSON 응답을 구문 분석하는 방법과 JSON 형식의 빈으로 요청을 보내는 방법까지 예시한다.

  @Autowired
  protected MockMvc mvc;

  private static final ObjectMapper MAPPER = new ObjectMapper()
    .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .registerModule(new JavaTimeModule());

  public static String requestBody(Object request) {
    try {
      return MAPPER.writeValueAsString(request);
    } catch (JsonProcessingException e) {
      throw new RuntimeException(e);
    }
  }

  public static <T> T parseResponse(MvcResult result, Class<T> responseClass) {
    try {
      String contentAsString = result.getResponse().getContentAsString();
      return MAPPER.readValue(contentAsString, responseClass);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Test
  public void testUpdate() {
    Book book = new Book();
    book.setTitle("1984");
    book.setAuthor("Orwell");
    MvcResult requestResult = mvc.perform(post("http://example.com/book/")
      .contentType(MediaType.APPLICATION_JSON)
      .content(requestBody(book)))
      .andExpect(status().isOk())
      .andReturn();
    UpdateBookResponse updateBookResponse = parseResponse(requestResult, UpdateBookResponse.class);
    assertEquals("1984", updateBookResponse.getTitle());
    assertEquals("Orwell", updateBookResponse.getAuthor());
  }

여기 보시다시피Book요청 DTO 및UpdateBookResponseJSON에서 구문 분석된 응답 객체.잭슨네 집을 바꾸고 싶을지도 모른다.ObjectMapper배열

한 가지 가능한 접근법은 단순히 다음을 포함하는 것이다.gson종속성:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
</dependency>

그리고 검증하기 위해 값을 구문 분석하십시오.

@RunWith(SpringRunner.class)
@WebMvcTest(HelloController.class)
public class HelloControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private HelloService helloService;

    @Before
    public void before() {
        Mockito.when(helloService.message()).thenReturn("hello world!");
    }

    @Test
    public void testMessage() throws Exception {
        MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.get("/"))
                .andExpect(status().isOk())
                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON_VALUE))
                .andReturn();

        String responseBody = mvcResult.getResponse().getContentAsString();
        ResponseDto responseDto
                = new Gson().fromJson(responseBody, ResponseDto.class);
        Assertions.assertThat(responseDto.message).isEqualTo("hello world!");
    }
}

또 다른 옵션은 다음과 같다.

when:

def response = mockMvc.perform(
            get('/path/to/api')
            .header("Content-Type", "application/json"))

then:

response.andExpect(status().isOk())
response.andReturn().getResponse().getContentAsString() == "what you expect"

사용할 수 있다getContentAsString응답 데이터를 문자열로 가져오는 방법.

    String payload = "....";
    String apiToTest = "....";
    
    MvcResult mvcResult = mockMvc.
                perform(post(apiToTest).
                content(payload).
                contentType(MediaType.APPLICATION_JSON)).
                andReturn();
    
    String responseData = mvcResult.getResponse().getContentAsString();

링크를 참고하여 테스트 신청을 할 수 있다.

String body = mockMvc.perform(bla... bla).andReturn().getResolvedException().getMessage()

이렇게 하면 반응의 본체를 얻을 수 있을 것이다."사용자 이름이 이미 사용 중"인 경우.

참조URL: https://stackoverflow.com/questions/18336277/how-to-check-string-in-response-body-with-mockmvc

반응형