Kann man die Anzahl der Mitglieder, die JsonPath verwenden, zählen?
Verwendung von spring mvc test Ich teste einen Controller, der generiert
{"foo": "oof", "bar": "rab"}
mit
standaloneSetup(new FooController(fooService)).build()
.perform(get("/something").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk())
.andExpect(jsonPath("$.foo").value("oof"))
.andExpect(jsonPath("$.bar").value("rab"));
Ich möchte sicherstellen, dass keine anderen Mitglieder im generierten Json anwesend sind. Hoffentlich durch Zählen mit JsonPath. Ist es möglich? Alternative Lösungen sind ebenfalls willkommen.
So testen Sie die Größe von array: jsonPath("$", hasSize(4))
Mitglieder von object zählen: jsonPath("$.*", hasSize(4))
Das heißt Um diese API zu testen, wird ein array von 4 Elementen zurückgegeben:
zulässiger Wert: [1,2,3,4]
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$", hasSize(4)));
zum Testen dieser API wird ein object zurückgegeben, das 2 Mitglieder enthält:
zulässiger Wert: {"foo": "oof", "bar": "rab"}
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.*", hasSize(2)));
Ich verwende Hamcrest Version 1.3 und Spring Test 3.2.5.RELEASE
Anmerkung: Sie müssen die Abhängigkeit von hamcrest-library und import static org.hamcrest.Matchers.*;
angeben, damit hasSize () funktioniert.
Ich habe mich heute damit beschäftigt. Es scheint nicht so, als wäre dies in den verfügbaren Behauptungen implementiert. Es gibt jedoch eine Methode zum Übergeben eines org.hamcrest.Matcher
-Objekts. Damit kann man so etwas machen:
final int count = 4; // expected count
jsonPath("$").value(new BaseMatcher() {
@Override
public boolean matches(Object obj) {
return obj instanceof JSONObject && ((JSONObject) obj).size() == count;
}
@Override
public void describeTo(Description description) {
// nothing for now
}
})
Wir können JsonPath-Funktionen wie size()
oder length()
wie folgt verwenden:
@Test
public void givenJson_whenGetLengthWithJsonPath_thenGetLength() {
String jsonString = "{'username':'jhon.user','email':'[email protected]','age':'28'}";
int length = JsonPath
.parse(jsonString)
.read("$.length()");
assertThat(length).isEqualTo(3);
}
oder einfach nach net.minidev.json.JSONObject
analysieren und de size erhalten:
@Test
public void givenJson_whenParseObject_thenGetSize() {
String jsonString = "{'username':'jhon.user','email':'[email protected]','age':'28'}";
JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonString);
assertThat(jsonObject)
.size()
.isEqualTo(3);
}
In der Tat scheint der zweite Ansatz besser zu sein als der erste. Ich habe einen JMH-Leistungstest durchgeführt und erhalte folgende Ergebnisse:
| Benchmark | Mode | Cnt | Score | Error | Units |
|-------------------------------------------------|-------|-----|-------------|--------------|-------|
| JsonPathBenchmark.benchmarkJSONObjectParse | thrpt | 5 | 3241471.044 | ±1718855.506 | ops/s |
| JsonPathBenchmark.benchmarkJsonPathObjectLength | thrpt | 5 | 1680492.243 | ±132492.697 | ops/s |
Den Beispielcode finden Sie hier .
wenn Sie com.jayway.jsonassert.JsonAssert
nicht in Ihrem Klassenpfad haben (was bei mir der Fall war), kann das Testen auf folgende Weise eine mögliche Problemumgehung sein:
assertEquals(expectedLength, ((net.minidev.json.JSONArray)parsedContent.read("$")).size());
[Anmerkung: Ich habe angenommen, dass der Inhalt des Json immer ein Array ist]
Sie können auch die Methoden im jsonpath verwenden, also statt
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.*", hasSize(2)));
du kannst tun
mockMvc.perform(get(API_URL))
.andExpect(jsonPath("$.length()", is(2)));