别再傻等接口了!用Playwright的Route拦截,5分钟搞定Mock数据(Python版)
别再傻等接口了!用Playwright的Route拦截,5分钟搞定Mock数据(Python版)
前端开发中最令人抓狂的瞬间,莫过于后端接口还没准备好,而你的页面逻辑已经写了一半。我曾经在一个电商项目里,因为支付接口延迟交付,整个团队被迫停滞了两周。直到发现了Playwright的Route拦截功能——原来我们完全可以在浏览器层面模拟任意接口响应,从此告别被动等待。
1. 为什么你需要掌握Route拦截技术
想象这样一个场景:凌晨两点,你正在赶制一个紧急需求,前端页面需要展示用户订单列表。但后端同事早已下班,接口返回的依然是{"error": "under maintenance"}。传统做法可能是手动修改本地JSON文件或者启动一个Mock服务器,但这些方案要么太原始,要么太重。
Playwright的Route拦截提供了第三种可能——直接在浏览器层面劫持特定请求。这意味着:
- 无需后端配合,独立完成全流程开发
- 模拟网络延迟、错误状态等真实场景
- 快速验证前端异常处理逻辑
- 实现自动化测试中的复杂用例构造
# 典型使用场景示例 from playwright.sync_api import sync_playwright def mock_user_api(route, request): if request.url.endswith("/api/user/profile"): route.fulfill( status=200, json={"name": "测试用户", "vip": True}, headers={"Content-Type": "application/json"} ) with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() page.route("**/api/user/*", mock_user_api) page.goto("https://your-app.com/profile") # 页面将收到我们预设的模拟数据2. 五分钟快速上手:基础拦截实战
2.1 安装与环境准备
确保已安装Python 3.7+和最新版Playwright:
pip install playwright playwright install2.2 三种核心拦截模式对比
| 方法 | 适用场景 | 示例场景 | 执行效率 |
|---|---|---|---|
continue() | 仅监控不修改 | 性能指标采集 | 最高 |
fulfill() | 完全模拟响应 | 开发环境Mock数据 | 高 |
abort() | 阻断特定请求 | 屏蔽广告追踪脚本 | 中 |
2.3 第一个拦截实例:替换用户数据
假设我们需要模拟用户VIP状态:
def mock_vip_user(route): route.fulfill( status=200, json={"level": "diamond", "expires": "2099-01-01"}, headers={"Cache-Control": "no-store"} ) page.route("**/api/membership", mock_vip_user)提示:在开发过程中,可以将这些拦截规则保存为独立模块,通过环境变量控制是否启用Mock
3. 高级应用技巧:应对复杂场景
3.1 动态响应生成
当需要根据请求参数返回不同数据时:
def dynamic_response(route, request): search_params = dict(parse_qs(urlparse(request.url).query)) user_id = search_params.get("uid", [""])[0] route.fulfill( json={"id": user_id, "avatar": f"https://avatar.com/{user_id}.jpg"} ) page.route("**/api/user?*", dynamic_response)3.2 混合使用拦截策略
有时我们需要组合多种拦截方式:
def hybrid_interception(route, request): if "analytics" in request.url: route.abort() # 屏蔽分析请求 elif request.method == "POST": route.continue_() # 放行所有POST请求 else: # 修改GET请求头 headers = {**request.headers, "X-Mock": "true"} route.continue_(headers=headers)3.3 文件与二进制响应模拟
处理图片等二进制数据时:
def mock_image(route): with open("mock-avatar.png", "rb") as f: route.fulfill( status=200, body=f.read(), headers={"Content-Type": "image/png"} ) page.route("**/uploads/*.png", mock_image)4. 工程化实践:将Mock融入开发流程
4.1 配置文件管理
建议创建mock_responses.py模块集中管理:
# mock_responses.py MOCK_CONFIG = { "/api/login": { "status": 401, "json": {"error": "invalid_credentials"}, "enable": False }, "/api/products": lambda: { "items": [{"id": i, "name": f"商品{i}"} for i in range(1,6)] } } def apply_mocks(page): for path, config in MOCK_CONFIG.items(): if not config.get("enable", True): continue def handler(route): response = config() if callable(config) else config route.fulfill(**response) page.route(f"**{path}", handler)4.2 与自动化测试结合
在Pytest中使用夹具:
@pytest.fixture def mock_page(): with sync_playwright() as p: browser = p.chromium.launch() page = browser.new_page() apply_mocks(page) # 应用预设的Mock规则 yield page browser.close() def test_checkout_flow(mock_page): mock_page.goto("/checkout") # 断言会收到我们预设的模拟订单数据4.3 性能优化建议
- 对频繁拦截的路径使用正则匹配:
page.route(re.compile(r"/api/v\d+/products")) - 避免在拦截器中进行复杂计算
- 必要时使用
route.fetch()获取原始响应后再修改
async def modify_response(route): response = await route.fetch() # 获取原始响应 data = await response.json() data["modified"] = True await route.fulfill(response=response, json=data) page.route("**/api/data", modify_response)5. 常见问题与调试技巧
5.1 拦截失效的排查步骤
- 确认URL模式匹配正确(建议先用
console.log输出请求URL) - 检查是否在其他地方调用了
route.continue_() - 验证拦截器是否注册在页面导航之前
5.2 复杂匹配场景示例
# 同时匹配多个条件 def complex_matcher(route, request): if (request.method == "GET" and "/api" in request.url and "auth" in request.headers): print(f"拦截认证请求: {request.url}") route.fulfill(json={"token": "mock_token"}) page.route("**/*", complex_matcher)5.3 调试输出建议
在拦截器中添加诊断日志:
def debug_interceptor(route, request): print(f""" → 拦截到请求: URL: {request.url} Method: {request.method} Headers: {request.headers} PostData: {request.post_data} """) route.continue_() page.route("**/*", debug_interceptor)在实际项目中,我发现最实用的技巧是为不同的测试环境创建不同的Mock预设。比如在staging环境模拟网络延迟,在development环境返回极端测试数据。一个精心设计的Mock系统可以帮团队节省数百小时的等待时间。
