「JavaでJSONを比較する記事」を職場のSlackに貼ったところ、フロントでもJSONをいい感じに比較したいという依頼が来ました。
Jsonの比較
下記のRequestBodyを比較するようにする。
const response = { "animals": [ "gorilla", "human" ], "generate_date": "2020091910011234", "update_date": "2020092010023456" };
完全一致を行う
Requestと完全に一致させたJsonを用意して、Jestのexpect().toEqual()
を使用する。
test('完全比較', () => { const expected = { "animals": [ "gorilla", "human" ], "generate_date": "2020091910011234", "update_date": "2020092010023456" }; expect(response).toEqual(expected); });
特定の項目を完全無視する
無視したい項目に対して、expect.anything()
を設定します。
これで、キーが不足していた場合はエラーですが、どのような値だろうと無視して比較できます。
有効活用できる箇所:サーバー応答時間、ランダムな値等の中身に深い価値が無い場合。
test('特定の項目を完全に無視', () => { const expected = { "animals": [ "gorilla", "human" ], "generate_date": expect.anything(), "update_date": expect.anything() }; expect(response).toEqual(expected); });
正規表現で特定の項目を無視する
正規表現で比較したい項目に対して、expect.stringMatching(value)
を設定します。
完全に値の無視はしたくないが、もうちょっと強固に比較したい等に使用できます。
test('正規表現で特定の項目を比較', () => { const expected = { "animals": [ "gorilla", "human" ], "generate_date": expect.stringMatching("2020091910.*"), "update_date": expect.stringMatching("2020091910.*") // responseのupdate_dateは20200920なので、テスト失敗する }; expect(response).toEqual(expected); });
配列項目の順番は問いたくない
配列で比較するときによく使いそうです。
- 「データの返却」はServer
- 「データをどう表現するか。どうソートして見せるか」等はUI層
等々、責任が分かれている場合、データの順番は意識したくありません。
なので、配列の順番を意識せず、中身だけ確認したい場合はexpect.arrayContaining(array)
を使用したほうが良さそうです。
ただし、こちらを使用する場合は配列のサイズも確認すべきです。
arrayContainingは「対象の配列に、対象のオブジェクトが存在するか」という確認方法です。
期待値(expect)が多い時は対象のオブジェクトが存在しないのでエラーになってくれますが、期待値の方が少ない場合はすべて満たせているので、問題にならなくなります。
余計なデータが送られてこないことも確認したほうが良いので、サイズも確認すべきでしょう。
test('順番は無視', () => { const expected = { // humanだけにしてもエラーにならない。 "animals": expect.arrayContaining([ "human", "gorilla" ]), "generate_date": expect.anything(), "update_date": expect.anything() }; // arrayContainingつかうなら、サイズも見ておいたほうが良さそう expect(response.animals.length).toBe(2); expect(response).toEqual(expected); });
終わりに
JSON (JavaScript Object Notation)って名前ですから、Javascriptと親和性高いだろう。
そう考えてはいましたが、Jestだけで簡単に比較できるとは思いませんでした。
Javaの場合は、skyscreamer.JSONAssertとかJUnitと異なる別ライブラリを使う必要があったので、JSでも別ライブラリが必要かと考えてました。
Jestは日本語の公式ページもあるので、ぜひ参考にしてください。
私が興味なくて紹介しなかったが、有効なのもあるはずなので公式見てください。
ソースコード
require
を使って別ファイルから期待値や実値を読み込めるから、覚えると便利。