Jestでクラスインスタンスの比較をすると、"Received: serializes to the same string" と出てきて必ずテスト結果がFAILになる。


発生している問題

Jestのexpect().toEqual()でクラスインスタンスを比較すると、フィールドの値が同じでも何故かテスト結果がFAILになってしまう。

テストコード

class Person {
  constructor(public readonly name: string, public readonly age: number) {}

  public greet = (): string => `${this.age}歳の${this.name}です。`
}

it('クラスインスタンスが一致している。', () => {
  const taro1 = new Person('taro', 20)
  const taro2 = new Person('taro', 20)

  expect(taro1).toEqual(taro2)
})

テスト結果

 FAIL  src/tests/redux/scoreHistory/reducers/addNotes.test.ts
  ● クラスインスタンスが一致している。

    expect(received).toEqual(expected) // deep equality

    Expected: {"age": 20, "greet": [Function anonymous], "name": "taro"}
    Received: serializes to the same string

      56 |   const taro2 = new Person('taro', 20)
      57 | 
    > 58 |   expect(taro1).toEqual(taro2)
         |                 ^
      59 | })
      60 | 

インスタンスのフィールドは全て同じだが、テスト結果はFAILになってしまっている。

解決策

以下のように、比較するインスタンスをJSON.stringify()で囲ってあげたらテストが通るようになった。

// 省略

it('クラスインスタンスが一致している。', () => {
  const taro1 = new Person('taro', 20)
  const taro2 = new Person('taro', 20)

  expect(JSON.stringify(taro1)).toEqual(JSON.stringify(taro2))
})

これでいいのか?と、疑問を持ちつつも、明確な問題点が思いつくわけでもなく、テストも正しく行えているのでとりあえずいいだろう。

備考

解決するまでの過程で色々試した結果、クラスのメソッドを全部コメントアウトするとJSON.stringifyで囲まなくてもテストが正しく通ることが分かった。
今回の解決策には関係ないが、もしちゃんと解決するなら役に立つ情報かもしれない。