hitung anggota dengan jsonpath?

103

Apakah mungkin menghitung jumlah anggota yang menggunakan JsonPath?

Menggunakan uji mvc pegas, saya menguji pengontrol yang menghasilkan

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

dengan

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

Saya ingin memastikan bahwa tidak ada anggota lain yang hadir di json yang dihasilkan. Semoga dengan menghitungnya menggunakan jsonPath. Apa itu mungkin? Solusi alternatif juga diterima.

NA.
sumber

Jawaban:

233

Untuk menguji ukuran larik :jsonPath("$", hasSize(4))

Untuk menghitung anggota objek :jsonPath("$.*", hasSize(4))


Yaitu untuk menguji bahwa API mengembalikan larik 4 item:

nilai yang diterima: [1,2,3,4]

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

untuk menguji bahwa API mengembalikan objek yang berisi 2 anggota:

nilai yang diterima: {"foo": "oof", "bar": "rab"}

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

Saya menggunakan Hamcrest versi 1.3 dan Spring Test 3.2.5.RELEASE

hasSize (int) javadoc

Catatan: Anda perlu menyertakan dependensi hamcrest-library dan import static org.hamcrest.Matchers.*;agar hasSize () berfungsi.

lopisan
sumber
2
@mattb - jika menggunakan Maven, jangan tambahkan hamcrest-allsebagai ketergantungan, tetapi gunakan hamcrest-library: code.google.com/p/hamcrest/wiki/HamcrestDistributables
Adam Michalik
1
Bagaimana jika seseorang tidak tahu ukurannya dan ingin mendapatkannya?
zygimantus
2
@ menuka-ishan - Saya tidak berpikir itu usang, menurut: MockMvcResultMatchers.jsonPath () javadoc
lopisan
@zygimantus Anda harus menghitung ukuran semua bidang di Objek / Array Anda, baik dari kode sumber atau alat pengembang browser web yang memeriksa responsnya.
cellepo
12

Anda juga dapat menggunakan metode di dalam jsonpath, jadi sebagai ganti

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

Anda dapat melakukan

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

Kita bisa menggunakan fungsi JsonPath seperti size()atau length(), seperti ini:

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

Atau cukup parse net.minidev.json.JSONObjectdan dapatkan ukurannya:

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

Memang, pendekatan kedua terlihat berkinerja lebih baik daripada yang pertama. Saya melakukan tes kinerja JMH dan saya mendapatkan hasil sebagai berikut:

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

Kode contoh dapat ditemukan di sini .

SHoko
sumber
4

Aku berurusan dengan ini sendiri hari ini. Sepertinya ini tidak diterapkan dalam pernyataan yang tersedia. Namun, ada metode untuk melewatkan suatu org.hamcrest.Matcherobjek. Dengan itu Anda dapat melakukan sesuatu seperti berikut:

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

jika Anda tidak memiliki com.jayway.jsonassert.JsonAssertclasspath Anda (yang terjadi pada saya), pengujian dengan cara berikut mungkin merupakan solusi yang mungkin:

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

[catatan: saya berasumsi bahwa konten json selalu berupa array]

Tanvir
sumber