Mitglieder mit jsonpath zählen?

103

Ist es möglich, die Anzahl der Mitglieder mit JsonPath zu zählen?

Mit dem Spring MVC Test teste ich 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 vorhanden sind. Hoffentlich durch Zählen mit jsonPath. Ist es möglich? Alternative Lösungen sind ebenfalls willkommen.

N / A.
quelle

Antworten:

231

So testen Sie die Größe des Arrays :jsonPath("$", hasSize(4))

So zählen Sie Mitglieder eines Objekts :jsonPath("$.*", hasSize(4))


Das heißt, um zu testen, dass die API ein Array von 4 Elementen zurückgibt :

akzeptierter Wert: [1,2,3,4]

mockMvc.perform(get(API_URL))
       .andExpect(jsonPath("$", hasSize(4)));

Um zu testen, ob die API ein Objekt mit 2 Mitgliedern zurückgibt :

akzeptierter 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

hasSize (int) javadoc

Hinweis: Sie müssen die Abhängigkeit von der Hamcrest-Bibliothek import static org.hamcrest.Matchers.*;einschließen, damit hasSize () funktioniert.

Lopisan
quelle
2
@ Mattb - Wenn Sie Maven verwenden, fügen Sie nicht hamcrest-allals Abhängigkeit hinzu, sondern verwenden Sie hamcrest-library: code.google.com/p/hamcrest/wiki/HamcrestDistributables
Adam Michalik
1
Was ist, wenn man die Größe nicht kennt und sie bekommen möchte?
Zygimantus
2
@ menuka-ishan - Ich glaube nicht, dass es veraltet ist, laut: MockMvcResultMatchers.jsonPath () javadoc
lopisan
@zygimantus Sie müssen die Größe aller Felder in Ihrem Objekt / Array hochzählen, entweder anhand des Quellcodes oder anhand der Überprüfung der Antwort durch Webbrowser-Entwicklertools.
Cellepo
12

Sie können auch die Methoden im jsonpath verwenden, also anstelle von

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.*", hasSize(2)));

du kannst tun

mockMvc.perform(get(API_URL))
   .andExpect(jsonPath("$.length()", is(2)));
Stalet
quelle
7

Wir können verwenden JsonPath Funktionen wie size()oder length(), wie folgt aus :

@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 analysieren net.minidev.json.JSONObjectund die Größe ermitteln:

@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 eine bessere Leistung zu erzielen als der erste. Ich habe einen JMH-Leistungstest durchgeführt und erhalte die folgenden 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 .

SHoko
quelle
4

Ich habe mich heute selbst damit befasst. Es scheint nicht so, als ob dies in den verfügbaren Zusicherungen implementiert ist. Es gibt jedoch eine Methode zum Übergeben eines org.hamcrest.MatcherObjekts. Damit können Sie etwa Folgendes tun:

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
    }
})
Ben
quelle
0

Wenn Sie keinen com.jayway.jsonassert.JsonAssertKlassenpfad 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 nahm an, dass der Inhalt des JSON immer ein Array ist]

Tanvir
quelle