JSONassertの紹介

JSONassertの概要

1. 概要

この記事では、JSONAssert libraryについて説明します。これは、JSONデータを理解し、そのデータを使用して複雑なJUnitテストを作成することに重点を置いたライブラリです。

2. メーベン依存

まず、Mavenの依存関係を追加しましょう。


    org.skyscreamer
    jsonassert
    1.5.0

ライブラリhereの最新バージョンを確認してください。

3. 単純なJSONデータの操作

3.1. LENIENTモードの使用

簡単なJSON文字列の比較からテストを始めましょう。

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

テストは予想されるJSON文字列として渡され、実際のJSON文字列は同じです。

比較mode 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);

ご覧のとおり、real変数には、予想されるStringには存在しない追加のフィールドzipが含まれています。 それでも、テストはパスします。

この概念は、アプリケーション開発に役立ちます。 これは、既存のテストを中断することなく、必要に応じて追加のフィールドを返し、APIを拡張できることを意味します。

3.2. STRICTモードの使用

前のサブセクションで説明した動作は、STRICT比較モードを使用して簡単に変更できます。

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

上記の例ではassertNotEquals()を使用していることに注意してください。

3.3. JSONCompareModeの代わりにBooleanを使用する

比較モードは、JSONCompareModeの代わりにbooleanを使用するオーバーロードメソッドを使用して定義することもできます。ここで、LENIENT = falseおよびSTRICT = 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. 論理比較

前に説明したように、JSONAssertはデータの論理比較を行います。 これは、JSONオブジェクトを処理する際に要素の順序が重要でないことを意味します。

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

厳密かどうかにかかわらず、上記のテストは両方の場合に合格します。

論理比較の別の例は、同じ値に異なるタイプを使用することで実証できます。

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

ここで最初に注意することは、前の例で使用したように、文字列の代わりにJSONObjectを使用していることです。 次のことは、expectedIntegerを使用し、actualDoubleを使用したことです。 両方の論理値12345が同じであるため、テストはタイプに関係なく合格します。

ネストされたオブジェクト表現がある場合でも、このライブラリは非常にうまく機能します。

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. ユーザー指定メッセージによるアサーション

すべてのassertEquals()およびassertNotEquals()メソッドは、最初のパラメーターとしてStringメッセージを受け入れます。 このメッセージは、テストが失敗した場合に意味のあるメッセージを提供することにより、テストケースのカスタマイズを提供します。

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

障害が発生した場合、エラーメッセージ全体がより意味があります。

Only one field is expected: name
Unexpected: id

最初の行はユーザーが指定したメッセージで、2行目はライブラリが提供する追加のメッセージです。

4. JSON配列の操作

JSONオブジェクトと比較すると、JSON配列の比較規則は少し異なります。

4.1. 配列内の要素の順序

最初の違いは、the order of elements in an array has to be exactly same in STRICT comparison modeです。 ただし、LENIENT比較モードの場合、順序は重要ではありません。

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

これは、APIが並べ替えられた要素の配列を返すシナリオで非常に役立ち、応答が並べ替えられているかどうかを確認する必要があります。

4.2. 配列内の拡張要素

もう1つの違いは、extended 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);

上記の例は、LENIENT比較モードを使用しても、期待される配列の項目が実際の配列の項目と正確に一致する必要があることを明確に示しています。 単一の要素であっても、追加または削除すると失敗します。

4.3. アレイ固有の操作

また、配列の内容をさらに検証するためのいくつかの他の手法もあります。

配列のサイズを確認したいとします。 これは、具体的な構文を期待値として使用することで実現できます。

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

String“\{names:[4]}”は、配列の予想サイズを指定します。

別の比較手法を見てみましょう。

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

上記の例は、配列内のすべての要素が[1,5]の間の値で、1と5の両方を含む必要があることを確認します。 1未満または5を超える値がある場合、上記のテストは失敗します。

5. 高度な比較例

APIが複数のidsを返し、それぞれがInteger値であるユースケースを考えてみましょう。 これは、すべてのidsが単純な正規表現 ‘\d‘を使用して検証できることを意味します。

上記の正規表現は、CustomComparatorと組み合わせて、すべてのidsのすべての値に適用できます。 idsのいずれかが正規表現と一致しない場合、テストは失敗します。

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


上記の例の「\{id:x}」はプレースホルダーにすぎません。xは何にでも置き換えることができます。 正規表現パターン ‘\d‘が適用される場所です。 id自体は別のフィールドentry内にあるため、Customizationidの位置を指定し、CustomComparatorが比較を実行できるようにします。

6. 結論

この簡単な記事では、JSONAssertが役立つさまざまなシナリオを検討しました。 まずは非常に単純な例から始め、より複雑な比較に移りました。

もちろん、いつものように、ここで説明されているすべての例の完全なソースコードはover on GitHubにあります。