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?

Error: useRoutes() may be used only in the context of a <Router> component.

2
Posted at

はじめに

こんにちは!POMです。
現在、JISOUの課題でデジタル名刺アプリを開発中なのですが、
vitestでテストを実装している際に表記のエラーが出ましたので、
その解決方法を残します。

問題

今回のアプリではreact-router-domを使ったルーティングをしており、
main.tsxとApp.tsxは下記のようにしていました。

main.tsx

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
import { Provider } from './components/ui/provider.tsx'
import { BrowserRouter } from 'react-router-dom'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Provider>
        <App />
      </Provider>
    </BrowserRouter>
  </StrictMode>,
)
App.tsx
import { AppRouter } from './router/AppRouter'

function App() {
  return (
      <AppRouter />
  );
}

export default App
[参考] AppRouter.tsx

AppRouter.tsxのコードも載せておきます。

import { Top } from "../components/pages/Top"
import { CardRegister } from "../components/pages/CardRegister"
import { Cards } from "../components/pages/Cards"
import { Route, Routes } from "react-router-dom"
import { Page404 } from "../components/pages/Page404"

export const AppRouter = () => {
    return (
        <Routes>
            <Route path="/" element={<Top />} />
            <Route path="/cards/:id" element={<Cards />} />
            <Route path="/cards/register" element={<CardRegister />} />
            <Route path="*" element={<Page404 />} />
        </Routes>
    );
}

ーーー

今回、Top画面に対してのテストを下記のように実装していました。

【修正前】

Top.spec.tsx
import { render } from "@/test-utils/render";
import { screen } from "@testing-library/dom";
import { BrowserRouter, } from "react-router-dom";
import { beforeEach, describe, expect, test, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { Top } from "@/components/pages/Top";

const mockNavigate = vi.fn();
vi.mock(import("react-router-dom"), async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        useNavigate: () => mockNavigate,
    };
});

const user = userEvent.setup();

describe("Top", () => {
    beforeEach(() => {
        mockNavigate.mockClear();

        render(<Top />);
    });

    test("タイトルが表示されていること", async () => {
        const title = await screen.findByText("デジタル名刺アプリ");
        expect(title).toBeInTheDocument();
    });



});

今回はuseNavigateを使ってリンク遷移を行っている部分があり、
下記記事を参考にuseNavigateをモック化してたりもします。

https://qiita.com/shiva_it/items/48e92101a31e4a2ba50d

いざ修正前のコードにてテストを動かしたところ、
表記のエラーが出ました。

 FAIL  src/__tests__/Top.spec.tsx > Top > タイトルが表示されていること
Error: useRoutes() may be used only in the context of a <Router> component.

解決方法

結論、テストファイルについてもmain.tsx同様に
<BrowserRouter>でラップする必要がありました。

【修正後】

Top.spec.tsx
import { render } from "@/test-utils/render";
import { screen } from "@testing-library/dom";
import { BrowserRouter, } from "react-router-dom";
import { beforeEach, describe, expect, test, vi } from "vitest";
import userEvent from "@testing-library/user-event";
import { Top } from "@/components/pages/Top";

const mockNavigate = vi.fn();
vi.mock(import("react-router-dom"), async (importOriginal) => {
    const actual = await importOriginal();
    return {
        ...actual,
        useNavigate: () => mockNavigate,
    };
});

const user = userEvent.setup();

describe("Top", () => {
    beforeEach(() => {
        mockNavigate.mockClear();

        render(
            <BrowserRouter>
                <Top />
            </BrowserRouter>
        );
    });

    test("タイトルが表示されていること", async () => {
        const title = await screen.findByText("デジタル名刺アプリ");
        expect(title).toBeInTheDocument();
    });



});

おわりに

ちなみに、今回はChakraUI(v3)も使用しているので、
main.tsxで<Provider>でもラップしていますが、
そういった場合のテストでrender()を使用する際の
注意点は下記記事が参考になりました。

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?