One way to retrieve an arbitrary, generic value from the JSON response is to leverage the jsonPath() matcher from the MockMVC library and couple it with a custom matcher that captures all values it is asked to match.
First, the custom matcher:
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);
}
}
Now, use the custom matcher to capture values and use the jsonPath() matcher to identify what should be captured:
@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)));
}