web-dev-qa-db-ja.com

jsonpathでメンバーをカウントしますか?

JsonPathを使用してメンバーの数をカウントすることはできますか?

spring mvc test を使用して、生成するコントローラーをテストしています

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

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

生成されたjsonに他のメンバーが存在しないことを確認したいと思います。できれば、jsonPathを使用してカウントしてください。出来ますか?代替ソリューションも歓迎します。

86
NA.

arrayのサイズをテストするには:jsonPath("$", hasSize(4))

objectのメンバーをカウントするには:jsonPath("$.*", hasSize(4))


つまりAPIが4つのアイテムのarrayを返すことをテストするには:

許容値:[1,2,3,4]

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

aPIが2つのメンバーを含むobjectを返すことをテストするには:

許容値:{"foo": "oof", "bar": "rab"}

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

Hamcrestバージョン1.3とSpring Test 3.2.5.RELEASEを使用しています

hasSize(int)javadoc

注:hasSize()が機能するには、hamcrest-library依存関係とimport static org.hamcrest.Matchers.*;を含める必要があります。

191
lopisan

JsonPath functionssize()またはlength()のように使用できます。次のようになります。

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

または、単にnet.minidev.json.JSONObjectおよびサイズを取得します。

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

実際、2番目のアプローチは最初のアプローチよりもパフォーマンスが良いようです。 JMHパフォーマンステストを行ったところ、次の結果が得られました。

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

サンプルコードは here にあります。

5
SHoko

今日自分でこれを扱っています。これが利用可能なアサーションに実装されているようには見えません。ただし、org.hamcrest.Matcherオブジェクトを渡すメソッドがあります。それにより、次のようなことができます。

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

Jsonpath内でメソッドを使用することもできます。そのため、

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

できるよ

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

クラスパスにcom.jayway.jsonassert.JsonAssertがない場合(これは私の場合でした)、次の方法でテストすることで回避策が得られる可能性があります。

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

[注:jsonのコンテンツは常に配列であると仮定しました]

0
Tanvir