web-dev-qa-db-fra.com

compter les membres avec jsonpath?

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

Utilisation de spring mvc test 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é. J'espère en les comptant en utilisant jsonPath. C'est possible? Des solutions alternatives sont également les bienvenues.

77
NA.

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

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


C'est à dire. pour vérifier que l'API renvoie un array 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 retourne un object 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

Remarque: Vous devez inclure la dépendance hamcrest-library et import static org.hamcrest.Matchers.*; pour que hasSize () fonctionne.

169
lopisan

Cela fait moi-même aujourd'hui. Il ne semble pas que cela soit implémenté dans les assertions disponibles. Cependant, il existe une méthode pour passer un objet org.hamcrest.Matcher. 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
    }
})
4
Ben

Nous pouvons utiliser Les fonctions JsonPath like size() ou length(), comme ceci:

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

ou simplement en analysant net.minidev.json.JSONObject et en obtenant la taille:

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

En effet, la seconde approche semble mieux performer 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é ici .

2
SHoko

si vous n'avez pas com.jayway.jsonassert.JsonAssert sur votre chemin de classe (ce qui était le cas avec moi), tester de la manière suivante peut être une solution de contournement possible:

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

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

0
Tanvir

Vous pouvez également utiliser les méthodes à l’intérieur de jsonpath, donc au lieu de 

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

tu peux faire

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