Jestの比較メソッドについて


リファクタリングを行ってる時に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でも可

参考

等価性の比較と同一性 - JavaScript | MDN

Object.is() - JavaScript | MDN

Expect · Jest