Previous
Day 17 · API Testing
Next
Day 19 · Uploads, Downloads, Dialogs, and Frames
真实场景
Day 1860-120 minutesPlaywright QA hands-on drill

Day 18 - Network Interception and Mocking

今日目标

  • 掌握 page.route()
  • 能 mock 接口响应。
  • 能测试异常、空数据、慢响应等场景。

学习时间安排(60–120 分钟)

时间模块做什么
0-20 分钟核心概念与词汇读概念表,重点理解 route 的三种处理方式。
20-45 分钟官方文档阅读读 Network 文档的 mocking 部分和 API 测试的 mock 章节。
45-75 分钟实操练习对列表页完成正常/空/500 三种 mock 测试。
75-105 分钟示例代码改写给现有测试加慢响应和异常场景用例。
105-120 分钟复盘与作业完成 mock 场景清单,完成今日问题。

核心概念与词汇

English中文场景用法
page.route()路由拦截Use it when you intercept matching requests and decide what to do with them.
route.fulfill()伪造响应Use it when you return a mocked response without hitting the server.
route.continue()放行请求Use it when you let the request proceed, optionally modified.
route.abort()中止请求Use it when you simulate a failed or blocked request.
mock模拟Use it when you replace a real response with a controlled one.
stubUse it when you replace a service with a fixed response for testing.
intercept拦截Use it when you capture a request before it reaches the network.
empty state空状态Use it when you verify the UI's behavior with zero data.
error state错误状态Use it when you verify the UI's behavior when the backend fails.
slow response慢响应Use it when you simulate latency to test loading states.
wildcard pattern通配符匹配Use it when **/api/products matches any host prefix.

学习材料

  • 必读:[Network - Mock APIs](https://playwright.dev/docs/mock)
  • 必读:[Network - Modify API responses](https://playwright.dev/docs/mock#modify-api-responses)(了解变体)
  • 选读:[Network - Abort requests](https://playwright.dev/docs/network#abort-requests)

重点理解

Mock 示例:

await page.route('**/api/products', async route => {
  await route.fulfill({
    status: 200,
    contentType: 'application/json',
    body: JSON.stringify([
      { id: 1, name: 'Mock Product' }
    ]),
  });
});

模拟错误:

await page.route('**/api/products', async route => {
  await route.fulfill({
    status: 500,
    body: 'Internal Server Error',
  });
});

模拟延迟:

await page.route('**/api/products', async route => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  await route.continue();
});

实操步骤

对一个列表页面做 3 种测试:

  1. 正常返回数据。
  2. 返回空数组。
  3. 返回 500 错误。

断言页面分别显示:

  • 列表内容。
  • Empty state。
  • Error message。

示例代码

import { test, expect } from '@playwright/test';

test('shows empty state when no data', async ({ page }) => {
  await page.route('**/api/products', route =>
    route.fulfill({ status: 200, contentType: 'application/json', body: '[]' })
  );
  await page.goto('/products');
  await expect(page.getByText('No products yet')).toBeVisible();
});

test('shows error message when backend fails', async ({ page }) => {
  await page.route('**/api/products', route =>
    route.fulfill({ status: 500, body: 'Internal Server Error' })
  );
  await page.goto('/products');
  await expect(page.getByText('Something went wrong')).toBeVisible();
});

常见坑

  • mock 后不再有真实请求,误以为页面 bug 而其实是 mock 数据写错了。
  • 通配符写窄了(如 https://api.example.com/products),请求带查询参数就拦不到。
  • 用 mock 全部替代真实 E2E,导致真实接口回归没人管。
  • mock 的响应结构和真实接口脱节,前端更新后测试全绿但线上全红。
  • 忘记 mock 情况下测试跑的是真实接口,数据被污染。

今日产出

  • 一个网络 mock 测试文件。
  • 一份 mock 场景清单。

今日问题

  1. page.route() 解决什么问题?
  2. Mock 是否能替代真实 E2E?
  3. 什么时候应该使用真实接口?
  4. 如何避免 mock 数据和真实接口脱节?
  5. Mock 慢响应能测试什么?

复盘要点

  • Mock 的价值是“确定性”:空数据、错误、慢响应这些真实环境难造的场景,mock 一秒钟就绪。
  • 分层策略:mock 用于前端状态覆盖,真实接口用于集成与端到端,两者都要有。
  • mock 与契约脱节是最大风险,团队有接口契约文档时,mock 数据应来自契约样例。

AI 时代扩展:AI 辅助 Playwright 测试

新增概念

English中文
contract-based mock基于契约的 mock
scenario simulation场景模拟
mock data generationmock 数据生成

适用场景

让 AI 根据接口契约生成不同场景的 mock 响应体(正常/空/错误/慢),或者审查你的 mock 数据是否与真实接口结构一致。

可复用表达 / 提示词

这是接口契约:GET /api/products 返回 { id, name, price }[]。请生成正常、空、500 三种 mock 响应体和对应测试。
请审查我的 mock 数据是否与真实接口结构一致,找出字段名、类型、嵌套结构的差异。

追问加练

  • AI 生成的 mock 数据如何验证和真实接口一致?
  • 慢响应 mock 的延时设多少合适?依据是什么?
  • 哪些场景下 mock 是唯一可行的测试手段?

今日作业

  • 完成 3 种 mock 场景测试并跑通。
  • 完成“mock 场景清单”:正常/空/错误/慢/未授权等至少 6 种。
  • 让 AI 按你的接口契约生成 mock 数据,和真实响应对比修正。

自检清单

Previous
Day 17 · API Testing
Next
Day 19 · Uploads, Downloads, Dialogs, and Frames