prosource

Spring MockMVC 사용 시 JSON 응답에서 값을 추출하는 방법

probook 2023. 3. 9. 22:09
반응형

Spring MockMVC 사용 시 JSON 응답에서 값을 추출하는 방법

POST 요구를 받아들이는 엔드포인트가 있다.JSON 응답에서 새로 생성된 엔티티의 ID를 얻고 싶습니다.

아래는 제가 시도하고 있는 코드의 일부입니다.

mockMvc.perform(post("/api/tracker/jobs/work")
        .contentType(TestUtil.APPLICATION_JSON_UTF8)
        .content(TestUtil.convertObjectToJsonBytes(workRequest)))
        .andExpect(status().isCreated());

이 ID를 얻으면 새로 생성된 엔티티에 대해 데이터베이스에 쿼리를 하고 다음과 같은 어설션을 수행합니다.

Work work = work service.findWorkById(id);

assertThat(work.getJobItem().getJobItemName()).isEqualTo(workRequest.getJobItem().getJobItemName());
assertThat(work.getJobItem().getQuantities()).hasSize(workRequest.getQuantities().size());
assertThat(work.getJobItem().getQuantityPools()).hasSize(workRequest.getQuantities().size());

간단하게 사용할 수 있습니다.JsonPath.read결과 객체:

MvcResult result = mockMvc.perform(post("/api/tracker/jobs/work")
    .contentType(TestUtil.APPLICATION_JSON_UTF8)
    .content(TestUtil.convertObjectToJsonBytes(workRequest)))
    .andExpect(status().isCreated())
    .andReturn();    

String id = JsonPath.read(result.getResponse().getContentAsString(), "$.id")

Work work = workService.findWorkById(id);

...

Spring MockMVC 결과 핸들러를 사용하여 문제를 해결했습니다.JSON 문자열을 오브젝트로 변환하여 ID를 얻을 수 있도록 테스트 유틸리티를 만들었습니다.

변환 유틸리티:

 public static <T>  Object convertJSONStringToObject(String json, Class<T> objectClass) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

    JavaTimeModule module = new JavaTimeModule();
    mapper.registerModule(module);
    return mapper.readValue(json, objectClass);
}

유닛 테스트:

 @Test
@Transactional
public void createNewWorkWorkWhenCreatedJobItemAndQuantitiesPoolShouldBeCreated() throws Exception {

    mockMvc.perform(post("/api/tracker/jobs/work")
        .contentType(TestUtil.APPLICATION_JSON_UTF8)
        .content(TestUtil.convertObjectToJsonBytes(workRequest)))
        .andExpect(status().isCreated())
        .andDo(mvcResult -> {
            String json = mvcResult.getResponse().getContentAsString();
            workRequestResponse = (WorkRequestResponse) TestUtil.convertJSONStringToObject(json, WorkRequestResponse.class);
        });

    Work work = workService.findWorkById(workRequestResponse.getWorkId());

    assertThat(work.getJobItem().getJobItemName()).isEqualTo(workRequest.getJobItem().getJobItemName());
    assertThat(work.getJobItem().getQuantities()).hasSize(workRequest.getQuantities().size());
    assertThat(work.getJobItem().getQuantityPools()).hasSize(workRequest.getQuantities().size());
}

JSON 응답에서 임의의 범용 값을 취득하는 방법 중 하나는 MockMVC 라이브러리에서 jsonPath() 매처를 활용하여 일치하는 모든 값을 캡처하는 커스텀매처와 결합하는 것입니다.

먼저 커스텀 매처:

import org.hamcrest.BaseMatcher;

/**
 * Matcher which always returns true, and at the same time, captures the
 * actual values passed in for matching. These can later be retrieved with a
 * call to {@link #getLastMatched()} or {@link #getAllMatched()}.
 */
public static class CapturingMatcher extends BaseMatcher<Object> {

    private List<Object> matchedList = new ArrayList<>();

    @Override
    public boolean matches(Object matched) {
        matchedList.add(matched);
        return true;
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("any object");
    }

    /**
     * The last value matched.
     */
    public Object getLastMatched() {
        return matchedList.get(matchedList.size() - 1);
    }

    /**
     * All the values matched, in the order they were requested for
     * matching.
     */
    public List<Object> getAllMatched() {
        return Collections.unmodifiableList(matchedList);
    }
}

다음으로 커스텀 매처를 사용하여 값을 캡처하고 json Path() 매처를 사용하여 캡처해야 할 값을 지정합니다.

@Test
@WithMockUser(username = "reviewer", authorities = {ROLE_USER})
public void testGetRemediationAction() throws Exception {

    CapturingMatcher capturingMatcher = new CapturingMatcher();

    // First request a list of all the available actions
    mvc.perform(get("/api/remediation/action").accept(VERSION_1_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.content[*].remediations[*].id", hasSize(12)))
            .andExpect(jsonPath("$.content[*].remediations[*].id", capturingMatcher));

    // Grab an ID from one of the available actions
    Object idArray = capturingMatcher.getLastMatched();
    assertThat(idArray).isInstanceOf(JSONArray.class);
    JSONArray jsonIdArray = (JSONArray) idArray;
    String randomId = (String) jsonIdArray.get(new Random().nextInt(12));

    // Now retrieve the chosen action
    mvc.perform(get("/api/remediation/action/" + randomId).accept(VERSION_1_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id", is(randomId)));
}

언급URL : https://stackoverflow.com/questions/47763332/how-to-extract-value-from-json-response-when-using-spring-mockmvc

반응형