126 votes

Comment compter les membres avec jsonpath ?

Est-il possible de compter le nombre de membres en utilisant JsonPath ?

Utilisation de Test de Spring MVC Je teste un contrôleur qui génère

{"foo": "oof", "bar": "rab"}

avec :

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"));

Je voudrais m'assurer qu'aucun autre membre n'est présent dans le json généré. Si possible en les comptant à l'aide de jsonPath. Est-ce possible ? Les solutions alternatives sont également les bienvenues.

294voto

lopisan Points 1327

Pour tester la taille de tableau : jsonPath("$", hasSize(4))

Pour compter les membres de objet : jsonPath("$.*", hasSize(4))


C'est-à-dire pour tester que l'API renvoie un fichier tableau de 4 éléments :

valeur acceptée : [1,2,3,4]

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

pour tester que l'API renvoie un objet contenant 2 membres :

valeur acceptée : {"foo": "oof", "bar": "rab"}

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

J'utilise Hamcrest version 1.3 et Spring Test 3.2.5.RELEASE.

hasSize(int) javadoc

Note : Vous devez inclure les dépendances hamcrest-library et import static org.hamcrest.Matchers.*; pour que hasSize() fonctionne.

23voto

stalet Points 823

Vous pouvez également utiliser les méthodes à l'intérieur du jsonpath, ainsi au lieu de

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

vous pouvez faire

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

10voto

SHoko Points 539

Nous pouvons utiliser Fonctions JsonPath comme size() o length() comme ceci :

@Test
public void givenJson_whenGetLengthWithJsonPath_thenGetLength() {
    String jsonString = "{'username':'jhon.user','email':'jhon@company.com','age':'28'}";

    int length = JsonPath
        .parse(jsonString)
        .read("$.length()");

    assertThat(length).isEqualTo(3);
}

Ou simplement l'analyse syntaxique en net.minidev.json.JSONObject et obtenir la taille :

@Test
public void givenJson_whenParseObject_thenGetSize() {
    String jsonString = "{'username':'jhon.user','email':'jhon@company.com','age':'28'}";

    JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonString);

    assertThat(jsonObject)
        .size()
        .isEqualTo(3);
}

En effet, la seconde approche semble plus performante que la première. J'ai fait un test de performance JMH et j'obtiens les résultats suivants :

| 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 |

L'exemple de code peut être trouvé aquí .

4voto

Ben Points 86

Je me suis occupé de ça moi-même aujourd'hui. Il ne semble pas que cela soit implémenté dans les assertions disponibles. Cependant, il y a une méthode pour passer dans un fichier org.hamcrest.Matcher objet. Avec cela, vous pouvez faire quelque chose comme ce qui suit :

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
    }
})

0voto

Tanvir Points 82

Si vous n'avez pas com.jayway.jsonassert.JsonAssert dans votre classpath (ce qui était mon cas), tester de la manière suivante peut être une solution de contournement :

assertEquals(expectedLength, ((net.minidev.json.JSONArray)parsedContent.read("$")).size());

[note : j'ai supposé que le contenu du json est toujours un tableau].

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X