Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使...
Search
Tasuku Watanabe
March 13, 2026
Programming
580
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
モックわからないマン卒業記 ~振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ~
Tasuku Watanabe
March 13, 2026
More Decks by Tasuku Watanabe
See All by Tasuku Watanabe
useImperativeHandleで理解する クロージャと評価タイミング
tasukuwatanabe
1
110
axiosで作る:ファイルアップロード体験を改善する「Progress Toast」
tasukuwatanabe
0
620
Other Decks in Programming
See All in Programming
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
4
140
Are APIs Still Relevant in the AI Era?
soyuka
0
360
JAWS-UG 東京支部が始める、JAWS-UG支部コラボ / JAWS-UG lunchtime LT Collaboration
y0hgi
0
170
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
310
C#の現在地 進化の歴史と、AI時代の.NET Everywhere
neuecc
5
4.4k
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
18
19k
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
3k
Security issues being discussed on Web Platforms
petamoriken
0
1.3k
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
360
Turning Architecture into Unit Tests in the AI Era (NSSpain XIV)
steliosf
PRO
1
120
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
320
AgentCore CLI で進化した AWS での AI エージェントの作り方 : 必要な機能を必要な時に
icoxfog417
PRO
4
390
Featured
See All Featured
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
720
ラッコキーワード サービス紹介資料
rakko
1
5.1M
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
960
Taking LLMs out of the black box: A practical guide to human-in-the-loop distillation
inesmontani
PRO
3
2.4k
Discover your Explorer Soul
emna__ayadi
2
1.3k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
380
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
RailsConf 2023
tenderlove
30
1.6k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.3k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
1k
Transcript
モックわからないマン卒業記 振る舞いを起点に見直した、フロントエンドテストにおけるモックの使いどころ HRBrain 渡邉佑 2026-03-13 React Tokyo #14
自己紹介 渡邉 佑 ・HRBrain ・新潟県佐渡島出身 ・新卒で航海士→エンジニア ・PlaywrightでE2Eテスト実装中 ・X: @tasuku_web 2
フロントでテストを書く デグレを発生させず安心して機能開発したい AIでたくさんリファクタリングしたい。 → Vitest + React Testing Library でテストを書いている。
import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { Counter } from "./Counter"; test("ボタンをクリックするとカウントが増える", async () => { render(<Counter />); await userEvent.click(screen.getByRole("button", { name: "増やす" })); expect(screen.getByText("1")).toBeInTheDocument(); }); 3
モックという概念が登場 テストを書こうとすると、コンポーネント内部に外部の依存が潜んでいる。 function UserGreeting() { // propsや引数ではなく、コンポーネントが内部で直接参照している外部の値(= 外部依存) const {
data } = useFetchUser(); // API通信 const now = useCurrentTime(); // 現在時刻 const { userId } = useAuth(); // 認証状態 } 4
モックを使わないと何が起きるか テスト対象のコンポーネント APIを内部で呼び出しているコンポーネント export function UserGreeting() { // API通信が内部で走る const
{ data } = useFetchUser(); if (!data) return <p>読み込み中...</p>; return <p>こんにちは、{data.name} さん</p>; } モックなし:テストが書けない ・ネットワーク環境に依存する ・テストが遅い・不安定 ・エラー系など特定ケースの再現が難しい test("ユーザー名が表示される", async () => { render(<UserGreeting />); // 実際のAPIが走る → ネットワーク環境がなければ失敗する expect(await screen.findByText("こんにちは、Alice さん") }); 5
モックで依存を差し替えてテスト可能 ・ネットワーク不要・高速 ・テストしたいケースを自由に再現できる ・外部サービスの状態に左右されない import * as hooks from "./useFetchUser";
test("ユーザー名が表示される", async () => { vi.spyOn(hooks, "useFetchUser").mockReturnValue({ data: { name: "田中" }, }); render(<UserGreeting />); expect(screen.getByText("こんにちは、田中 さん")).toBeInTheDocument(); }); 6
実際のテストファイルではこうなりがち // ① モジュールモック vi.mock("./useRouter"); vi.mock("./useAuth"); // ② HTTPモック(MSW) const
server = setupServer( http.get("/api/users", () => HttpResponse.json([{ name: "田中" }])), ); beforeAll(() => server.listen()); afterAll(() => server.close()); beforeEach(() => { vi.useFakeTimers(); // ③ タイマーモック vi.setSystemTime(new Date("2026-01-01")); vi.mocked(useRouter).mockReturnValue({ push: vi.fn() }); vi.mocked(useAuth).mockReturnValue({ userId: "u1" }); }); test("ユーザー一覧が表示される", async () => { const onSelect = vi.fn(); // ④ モック関数 render(<UserListPage onSelect={onSelect} />); expect(await screen.findByText("田中")).toBeInTheDocument(); }); 7
「APIが呼ばれたこと」を検証するのはNG ❌ よくある検証 import { fetchUsers } from "./api"; vi.mock("./api");
test("ユーザー一覧を取得する", () => { render(<UserListPage />); // APIが呼ばれたことを確認 expect(fetchUsers).toHaveBeenCalledWith("/api/users"); }); なぜNGか ・URLが /api/v2/users に変わるだけで壊れる ・画面が正しく表示されていてもテストが失敗する = リファクタリングのたびにテストも壊れる 8
だから、振る舞いをテストする
「振る舞いをテストする」という考え方 確認すべきは「何が呼ばれたか」より「画面がどう振る舞うか」 // 実装を見る(useStateの更新を直接確認) expect(setCount).toHaveBeenCalledWith(1); // 振る舞いを見る(画面がどう変わるかを確認) expect(screen.getByText("1")).toBeInTheDocument(); ・内部実装を変えても壊れにくい( setCount
→ useReducer に変えてもテストはパスする) ・ユーザーの視点でテストを書ける(ユーザーが気にするのは画面の動作であり、内部実装ではない) ・テストが仕様書になる( 「この操作をするとこう表示される」という意図が明確になる) 10
「振る舞いをテストする」という考え方 API通信: 「fetchが呼ばれたか」より「結果が表示されるか」 // 実装を見る(fetchの呼び出しを直接確認) expect(mockFetch).toHaveBeenCalledWith("/api/users"); // 振る舞いを見る(取得したデータが画面に表示されるかを確認) expect(screen.getByText("田中太郎")).toBeInTheDocument(); ・
実装依存: fetch の呼び出し先URL が変わるだけでテストが壊れる。コンポーネントの「結果」 は正しくても失敗する ・ 振る舞いベース:URLが変わっても、別のライブラリに乗り換えても、画面に結果が出ればテスト はパスする 11
「振る舞いをテストする」という考え方 ルーティング: 「router.pushが呼ばれたか」より「画面が遷移したか」 // 実装を見る(router.pushの呼び出しを直接確認) expect(mockPush).toHaveBeenCalledWith("/dashboard"); // 振る舞いを見る(遷移後のページが表示されるかを確認) expect( screen.getByRole("heading",
{ name: "ダッシュボード" }), ).toBeInTheDocument(); 12
まとめ モックで外部依存を差し替える → テストが書けるようになる API通信・認証・時刻などを固定してテスト可能に でも多用すると、リファクタリング耐性が下がる 実装詳細(関数名・モジュール構造)に依存し、テストが壊れやすくなる だから、振る舞い(画面の動作)をテストする 「何が呼ばれたか」より「画面がどう変わるか」を確認する 13
ご清聴ありがとうございました