2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Vitest/React Testing Library】expected 2 to be 3 // Object.is equality

2
Last updated at Posted at 2026-03-26

はじめに

こんにちは!POMです。
React × TypeScriptでの学習記録アプリ開発において、
Vitest/React Testing Libraryによる
テストを実装していましたが、
その際に出た表記のエラー解決方法について記事に残します。

今回開発したアプリの詳細については、
下記記事になります。

問題

学習記録を新規登録できているかのテストにおいて、
Supabase上の実データに依存しないように、
Supabaseと通信する部分についてはモックにしたテスト実装を
行っていた際に、下記エラーが出ました。

expected 2 to be 3 // Object.is equality

解決方法

【修正前】

/src/__tests__/StudyRecord.test.tsx
const mockInitRecords = [
  new Record("1", "test1", 10),
  new Record("2", "test2", 20),
];

const mockRecords = vi.fn().mockResolvedValue(mockInitRecords);

vi.mock("@/lib/record", () => {
  return {
    GetAllRecords: () => mockRecords(),
    InsertRecord: vi.fn(),
    UpdateRecord: vi.fn(),
  };
});

describe("シン・学習記録アプリ", () => { 
  beforeEach(() => { 
    render(<StudyRecord />); 
  });

  test("登録できること", async () => { 
      const before = await screen.findAllByTestId("record");
      const openAddModalButton = await screen.findByRole("button", { name: "新規登録" });
      fireEvent.click(openAddModalButton); 
      
      const inputTitle = await screen.findByLabelText("学習内容"); 
      const inputTime = await screen.findByLabelText("学習時間"); 
      const submitButton = await screen.findByRole("button", { name: "登録" }); 
      
      // テスト用の記録を入力して登録
      fireEvent.change(inputTitle, { target: { value: "テスト記録" }, }); 
      fireEvent.change(inputTime, { target: { value: "2" }, }); 
      fireEvent.click(submitButton); 
      
      await waitFor(async () => { 
        const after = await screen.findAllByTestId("record"); 
        expect(after.length).toBe(before.length + 1);
      }); 
    }); 
  });
/src/domin/record/ts
export class Record {
    constructor(
        public id: string | undefined,
        public title: string,
        public time: number
    ) {}

    public static newRecord(
        id: string | undefined,
        title: string,
        time: number
    ): Record {
        return new Record(
            id,
            title,
            time
        );
    }
}

原因はモック部分で

InsertRecord: vi.fn(),

としており、何もしないことになっていたからでした。

  1. GetAllRecords() → 2件表示
  2. 登録ボタン押す
  3. InsertRecord()が呼ばれる
  4. データは増えない → テーブルは2件のまま

そこでexpected 3 received 2となり、表記のエラーになっていました。

【修正後】

InsertRecordでrecordsを増やすモックに修正。

const mockInitRecords = [
  new Record("1", "test1", 10),
  new Record("2", "test2", 20),
];

const mockRecords = vi.fn().mockResolvedValue(mockInitRecords);

vi.mock("@/lib/record", () => {
  return {
    GetAllRecords: () => mockRecords(),
    InsertRecord: vi.fn(async (record: Record) => {
      mockInitRecords.push(record);
    }),



  };
});

合わせてbeforeEach部分でテストごとにモックデータを
初期状態に戻すようにも修正しています。


describe("シン・学習記録アプリ", () => {
  beforeEach(() => {
    mockInitRecords.length = 0;
    mockInitRecords.push(
      new Record("1", "test1", 10),
      new Record("2", "test2", 20)
    );
    render(<StudyRecord />);
  });



});

おわりに

いざ修正前のコードを見ると
そりゃあそうだよな・・・というところで
エラーになっているのですが、
沼にハマっていると実際のテスト部分のコードしか
見ていなかったりと意外と気づかないものです。

切り分けしながら、
処理の流れを丁寧に追っていきたいです。

参考

今回直したソースコードの詳細はGitHubにて。

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてくださ!
▼▼▼

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?