Einführung in JSONassert

Einführung in JSONassert

1. Überblick

In diesem Artikel werfen wir einen Blick aufJSONAssert library - eine Bibliothek, die sich darauf konzentriert, JSON-Daten zu verstehen und komplexeJUnit-Tests mit diesen Daten zu schreiben.

2. Maven-Abhängigkeit

Fügen wir zunächst die Maven-Abhängigkeit hinzu:


    org.skyscreamer
    jsonassert
    1.5.0

Bitte überprüfen Sie die neueste Version der Bibliothekhere.

3. Arbeiten mit einfachen JSON-Daten

3.1. Verwenden desLENIENT-Modus

Beginnen wir unsere Tests mit einem einfachen JSON-Zeichenfolgenvergleich:

String actual = "{id:123, name:\"John\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);

Der Test wird als die erwartete JSON-Zeichenfolge bestanden, und die tatsächliche JSON-Zeichenfolge ist dieselbe.

Der Vergleichmode LENIENT means that even if the actual JSON contains extended fields, the test will still pass:

String actual = "{id:123, name:\"John\", zip:\"33025\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);

Wie wir sehen können, enthält die Variablereal ein zusätzliches Feldzip, das in den erwartetenString nicht vorhanden ist. Trotzdem wird der Test bestehen.

Dieses Konzept ist nützlich in der Anwendungsentwicklung. Dies bedeutet, dass unsere APIs wachsen und bei Bedarf zusätzliche Felder zurückgeben können, ohne die vorhandenen Tests zu unterbrechen.

3.2. Verwenden desSTRICT-Modus

Das im vorherigen Unterabschnitt erwähnte Verhalten kann mithilfe des Vergleichsmodus vonSTRICTleicht geändert werden:

String actual = "{id:123,name:\"John\"}";
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, JSONCompareMode.STRICT);

Bitte beachten Sie die Verwendung vonassertNotEquals() im obigen Beispiel.

3.3. Verwenden vonBoolean Anstelle vonJSONCompareMode

Der Vergleichsmodus kann auch mithilfe einer überladenen Methode definiert werden, dieboolean anstelle vonJSONCompareMode verwendet, wobeiLENIENT = false undSTRICT = true:

String actual = "{id:123,name:\"John\",zip:\"33025\"}";
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT);
JSONAssert.assertEquals(
  "{id:123,name:\"John\"}", actual, false);

actual = "{id:123,name:\"John\"}";
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, JSONCompareMode.STRICT);
JSONAssert.assertNotEquals(
  "{name:\"John\"}", actual, true);

3.4. Der logische Vergleich

Wie zuvor beschrieben, führtJSONAssert einen logischen Vergleich der Daten durch. Dies bedeutet, dass die Reihenfolge der Elemente beim Umgang mit JSON-Objekten keine Rolle spielt:

String result = "{id:1,name:\"John\"}";
JSONAssert.assertEquals(
  "{name:\"John\",id:1}", result, JSONCompareMode.STRICT);
JSONAssert.assertEquals(
  "{name:\"John\",id:1}", result, JSONCompareMode.LENIENT);

Streng oder nicht, obiger Test besteht in beiden Fällen.

Ein weiteres Beispiel für einen logischen Vergleich kann anhand verschiedener Typen für denselben Wert demonstriert werden:

JSONObject expected = new JSONObject();
JSONObject actual = new JSONObject();
expected.put("id", Integer.valueOf(12345));
actual.put("id", Double.valueOf(12345));

JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT);

Das erste, was hier zu beachten ist, ist, dass wirJSONObject anstelle eines Strings verwenden, wie wir es für frühere Beispiele getan haben. Das nächste ist, dass wirInteger fürexpected undDouble füractual verwendet haben. Der Test wird unabhängig von den Typen bestanden, da der logische Wert 12345 für beide gleich ist.

Selbst wenn wir eine verschachtelte Objektdarstellung haben, funktioniert diese Bibliothek ziemlich gut:

String result = "{id:1,name:\"Juergen\",
  address:{city:\"Hollywood\", state:\"LA\", zip:91601}}";
JSONAssert.assertEquals("{id:1,name:\"Juergen\",
  address:{city:\"Hollywood\", state:\"LA\", zip:91601}}", result, false);

3.5. Behauptungen mit benutzerdefinierten Nachrichten

Alle MethodenassertEquals() undassertNotEquals() akzeptieren eineString-Nachricht als ersten Parameter. Diese Nachricht bietet einige Anpassungsmöglichkeiten für unsere Testfälle, indem sie im Fall von Testfehlern eine aussagekräftige Meldung ausgibt:

String actual = "{id:123,name:\"John\"}";
String failureMessage = "Only one field is expected: name";
try {
    JSONAssert.assertEquals(failureMessage,
      "{name:\"John\"}", actual, JSONCompareMode.STRICT);
} catch (AssertionError ae) {
    assertThat(ae.getMessage()).containsIgnoringCase(failureMessage);
}

Im Fehlerfall ist die gesamte Fehlermeldung sinnvoller:

Only one field is expected: name
Unexpected: id

Die erste Zeile ist die vom Benutzer angegebene Nachricht und die zweite Zeile ist die zusätzliche Nachricht, die von der Bibliothek bereitgestellt wird.

4. Arbeiten mit JSON-Arrays

Die Vergleichsregeln für JSON-Arrays unterscheiden sich im Vergleich zu JSON-Objekten geringfügig.

4.1. Die Reihenfolge der Elemente in einem Array

Der erste Unterschied ist, dassthe order of elements in an array has to be exactly same in STRICT comparison mode. Für den Vergleichsmodus vonLENIENTpielt die Reihenfolge jedoch keine Rolle:

String result = "[Alex, Barbera, Charlie, Xavier]";
JSONAssert.assertEquals(
  "[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.LENIENT);
JSONAssert.assertEquals(
  "[Alex, Barbera, Charlie, Xavier]", result, JSONCompareMode.STRICT);
JSONAssert.assertNotEquals(
  "[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.STRICT);

Dies ist in einem Szenario sehr nützlich, in dem die API ein Array sortierter Elemente zurückgibt und wir überprüfen möchten, ob die Antwort sortiert ist.

4.2. Die erweiterten Elemente in einem Array

Ein weiterer Unterschied ist, dassextended elements are not allowed when the dealing with JSON arrays:

String result = "[1,2,3,4,5]";
JSONAssert.assertEquals(
  "[1,2,3,4,5]", result, JSONCompareMode.LENIENT);
JSONAssert.assertNotEquals(
  "[1,2,3]", result, JSONCompareMode.LENIENT);
JSONAssert.assertNotEquals(
  "[1,2,3,4,5,6]", result, JSONCompareMode.LENIENT);

Das obige Beispiel zeigt deutlich, dass selbst im Vergleichsmodus vonLENIENTdie Elemente im erwarteten Array genau mit den Elementen im realen Array übereinstimmen müssen. Das Hinzufügen oder Entfernen eines einzelnen Elements führt zu einem Fehler.

4.3. Array-spezifische Operationen

Wir haben auch einige andere Techniken, um den Inhalt der Arrays weiter zu überprüfen.

Angenommen, wir möchten die Größe des Arrays überprüfen. Dies kann erreicht werden, indem eine konkrete Syntax als erwarteter Wert verwendet wird:

String names = "{names:[Alex, Barbera, Charlie, Xavier]}";
JSONAssert.assertEquals(
  "{names:[4]}",
  names,
  new ArraySizeComparator(JSONCompareMode.LENIENT));

String“\{names:[4]}” gibt die erwartete Größe des Arrays an.

Schauen wir uns eine andere Vergleichstechnik an:

String ratings = "{ratings:[3.2,3.5,4.1,5,1]}";
JSONAssert.assertEquals(
  "{ratings:[1,5]}",
  ratings,
  new ArraySizeComparator(JSONCompareMode.LENIENT));

Im obigen Beispiel wird überprüft, ob alle Elemente im Array einen Wert zwischen [1,5] (einschließlich 1 und 5) aufweisen müssen. Wenn ein Wert kleiner als 1 oder größer als 5 ist, schlägt der obige Test fehl.

5. Beispiel für einen erweiterten Vergleich

Betrachten Sie den Anwendungsfall, in dem unsere API mehrereids zurückgibt, wobei jeder Wert einInteger ist. Dies bedeutet, dass alleids mit einem einfachen regulären Ausdruck „\d“ überprüft werden können.

Der obige reguläre Ausdruck kann mit einemCustomComparator kombiniert und auf alle Werte allerids angewendet werden. Wenn einer derids nicht mit dem regulären Ausdruck übereinstimmt, schlägt der Test fehl:

JSONAssert.assertEquals("{entry:{id:x}}", "{entry:{id:1, id:2}}",
  new CustomComparator(
  JSONCompareMode.STRICT,
  new Customization("entry.id",
  new RegularExpressionValueMatcher("\\d"))));

JSONAssert.assertNotEquals("{entry:{id:x}}", "{entry:{id:1, id:as}}",
  new CustomComparator(JSONCompareMode.STRICT,
  new Customization("entry.id",
  new RegularExpressionValueMatcher("\\d"))));


Das "\{id:x}" im obigen Beispiel ist nichts anderes als ein Platzhalter - dasx kann durch irgendetwas ersetzt werden. Da dies der Ort ist, an dem das Regex-Muster '\d' angewendet wird. Da sichid selbst in einem anderen Feldentry befindet, gibtCustomization die Position vonid an, damitCustomComparator den Vergleich durchführen kann.

6. Fazit

In diesem kurzen Artikel haben wir uns verschiedene Szenarien angesehen, in denen JSONAssert hilfreich sein kann. Wir haben mit einem supereinfachen Beispiel begonnen und sind zu komplexeren Vergleichen übergegangen.

Natürlich kann wie immer der vollständige Quellcode aller hier diskutierten Beispieleover on GitHub gefunden werden.