はじめに
現在、TanStack Router を利用した SPA を開発しています。
最近、Integrationテスト(結合テスト)を実装することになったのですが、公式ドキュメントにテストに関する情報がなく、そもそもページの render をどうするのか?というところからつまづいたので、簡単にまとめました。
同じように困っている方の参考になれば幸いです。
目次
前提
ルーティング関連のライブラリ
"@tanstack/react-router": "^1.114.3"
"@tanstack/react-router-devtools": "^1.114.3"
テスト関連のライブラリ
"@testing-library/dom": "^10.4.0"
"@testing-library/jest-dom": "^6.6.3"
"@testing-library/react": "^16.3.0"
"@testing-library/user-event": "^14.6.1"
"@vitejs/plugin-react": "^4.3.4"
"jsdom": "^26.1.0"
"vite": "^6.1.0"
"vitest": "^3.1.4"
実装例
今回は下記の理由から、main.tsx
で定義している router
インスタンスをテストファイルでもimport
し、render(<RouterProvider router={router} />)
を使ってページをレンダリングすることにしました。
-
router
の定義を共通化でき、アプリ本番と同じ設定でテストが書ける - 初期化処理を新たに書かずに済むため、手軽に導入可能
- 複雑な context 設定や routeTree をテスト側で再構成しなくて済む
import { createRouter, RouterProvider } from '@tanstack/react-router';
- const router = createRouter({
+ export const router = createRouter({
routeTree,
context: {
...TanStackQueryProvider.getContext(),
},
defaultPreload: 'intent',
scrollRestoration: true,
defaultStructuralSharing: true,
defaultPreloadStaleTime: 0,
});
import { router } from "@/main";
import { RouterProvider } from "@tanstack/react-router";
import { describe, test } from "vitest";
// テストごとにnavigateして任意の初期URLに遷移させる
const customRender = async () => {
await router.navigate({
to: "/sample",
});
render(<RouterProvider router={router} />);
};
describe("/sample のテスト", () => {
test("××ボタンを押下すると、〇〇が表示されること", async () => {
customRender();
// 要素を取得して結果を検証
});
test("△△ボタンを押下すると、◻︎◻︎が表示されること", async () => {
customRender();
// 要素を取得して結果を検証
});
});
まとめ
今回は、main.tsx で定義している router インスタンスをテスト内でもそのまま利用する方法をご紹介しました。
ただ、この方法がベストプラクティスなのか?という疑問もあるので、今後は、テスト用に TestRouterProvider を別ファイルに定義して、router や context、必要な provider を柔軟に差し替えられるようにする構成も検討したいと思います。
より良い方法やパターンが見つかれば、あらためて記事としてまとめていく予定です。