リファクタリングを行ってる時にJavaScriptのテストの比較周りの知識が曖昧だったのでまとめます。
調べるきっかけとなったコード
is.test.ts
it("Jest's test", () => {
....
assert.deepStrictEqual(value, [{ id: 1, name: "aaaaa" }]);
});
JestでAssertionがエラーとなった。
is.test.ts
assert.deepStrictEqual(received, expected)
Expected value to deeply and strictly equal to:
[{"id": 1, "name": "aaaaa"}]
Received:
[{"id": 1, "name": "aaaaa"}]
Difference:
Compared values have no visual difference.
assert.deepStrictEqual
は値の完全一致と思い込んでいたので、なんで失敗するのだろう?と少しはまりました。
Jestの比較
Jestにも同様の関数が存在するので試した結果が以下。
is.test.ts
class LaCroix {
public flavor: any;
constructor(flavor: any) {
this.flavor = flavor;
}
}
it("同一の確認", () => {
// "レモン" === "レモン" -> 成功
expect("レモン").toBe("レモン");
// true === 1 -> 失敗
expect(true).toBe(1);
// 1 == true -> 成功
expect(1).toBeTruthy();
// LaCroix {
// "flavor": "レモン",
// }
// Object {
// "flavor": "レモン",
// }
// 値が同じなので成功
expect(new LaCroix("レモン")).toEqual({flavor: "レモン"});
// LaCroix {
// "flavor": 1,
// }
// Object {
// "flavor": "1",
// }
// 値が違うので失敗
expect(new LaCroix(1)).toEqual({flavor: '1'});
// LaCroix {
// "flavor": "レモン",
// }
// Object {
// "flavor": "レモン",
// }
// 値は同じだがオブジェクトの型が違うので失敗
expect(new LaCroix("レモン")).toStrictEqual({flavor: "レモン"});
// LaCroix {
// "flavor": "レモン",
// }
// LaCroix {
// "flavor": "レモン",
// }
// 値もオブジェクトの型も同じなので成功
expect(new LaCroix("レモン")).toStrictEqual(new LaCroix("レモン"));
// LaCroix {
// "flavor": "レモン",
// }
// Object {
// "flavor": "レモン",
// }
// 値は同じだがオブジェクトの型が違うので失敗
assert.deepStrictEqual(new LaCroix("レモン"), {flavor: "レモン"});
// LaCroix {
// "flavor": 1,
// }
// LaCroix {
// "flavor": "1",
// }
// 値もオブジェクトの型も同じなので成功
assert.deepStrictEqual(new LaCroix("レモン"), new LaCroix("レモン"));
});
名前的に=== (厳格な等価性比較)
とtoStrictEqual
が同じものと思っており、プリミティブ値に使ってたことがあります。
toBeTruthy
よりtoBe(true)
のほうが厳密なテストですね。
まとめ
プリミティブ値の比較を行う場合は toBe
を使う。
オブジェクトの値の比較を行う場合は toEqual
を使う。
オブジェクトの値、型の比較を行う場合は toStrictEqual
を使う。(assert.deepStrictEqual
でも可)