别再傻等接口了!用Playwright的Route拦截,5分钟搞定前端Mock数据(Python版)
别再傻等接口了用Playwright的Route拦截5分钟搞定前端Mock数据Python版前端开发最痛苦的时刻之一就是页面写好了却发现后端接口还没就绪。传统的Mock方案要么需要搭建额外的服务器要么依赖复杂的配置。但如果你正在使用Playwright进行自动化测试其实已经手握一个轻量级Mock工具——Route拦截系统。1. 为什么选择Playwright做Mock大多数开发者对Playwright的认知停留在自动化测试工具但它内置的请求拦截能力堪称前端开发的瑞士军刀。相比传统Mock方案零成本集成无需额外安装库Playwright本身已包含完整网络拦截功能精准控制可针对特定URL模式拦截其余请求正常放行动态响应支持根据请求参数生成不同响应数据无侵入性不影响现有代码逻辑随时开启/关闭# 典型使用场景示例 from playwright.sync_api import sync_playwright def mock_api(route, request): if /api/user in request.url: route.fulfill(json{name: Mock User, id: 123}) else: route.continue_() with sync_playwright() as p: browser p.chromium.launch() page browser.new_page() page.route(**/*, mock_api) # 关键拦截设置 page.goto(http://your-app.com)2. 五分钟快速上手Mock实战2.1 基础拦截配置实现一个完整的Mock只需要三个步骤创建路由规则使用page.route()指定要拦截的URL模式编写处理函数决定是继续请求(continue_)还是模拟响应(fulfill)定义响应内容包括状态码、headers和body数据# 模拟登录接口响应 def mock_login(route, request): if /api/login in request.url: route.fulfill( status200, headers{Content-Type: application/json}, body{token: mock_token, expires: 3600} ) else: route.continue_() page.route(**/api/*, mock_login)2.2 动态数据生成真正的实用场景需要根据请求参数返回不同数据。通过解析request对象可以实现def mock_search(route, request): if /api/search in request.url: # 从请求中获取查询参数 params request.url.split(?)[1] keyword next(v for k,v in [p.split() for p in params.split()] if k q) # 根据关键词返回不同结果 route.fulfill(json{ results: [fMock result for {keyword} #{i} for i in range(3)] }) else: route.continue_()3. 高级Mock技巧3.1 文件资源Mock除了API还可以拦截静态资源请求def mock_assets(route, request): if request.url.endswith(.css): route.fulfill(body/* 空样式表 */) elif request.url.endswith(.png): # 返回1x1透明像素图 route.fulfill(bodybase64.b64decode(iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII)) else: route.continue_()3.2 延迟响应模拟测试加载状态时可以人为添加延迟import time def delayed_response(route, request): if /api/slow in request.url: time.sleep(2) # 2秒延迟 route.fulfill(json{status: done}) else: route.continue_()3.3 错误场景模拟测试异常处理时可以模拟各种错误错误类型实现方式适用场景网络超时route.abort()测试请求失败处理服务端错误route.fulfill(status500)测试错误状态码处理无效JSONroute.fulfill(bodyhtml)测试数据解析错误处理def mock_errors(route, request): if /api/unstable in request.url: # 随机返回成功或失败 import random if random.random() 0.5: route.fulfill(status500) else: route.fulfill(json{data: success}) else: route.continue_()4. 与前端开发流程整合4.1 开发环境快速切换建议创建不同的profile来管理Mock规则# mock_profiles.py from typing import Dict, Callable profiles: Dict[str, Callable] { default: lambda r: r.continue_(), empty_api: lambda r: r.fulfill(json{}) if /api/ in r.url else r.continue_(), demo_data: lambda r: ( r.fulfill(jsonget_demo_data(r.url)) if /api/ in r.url else r.continue_() ) } def apply_profile(page, profile_name): page.unroute(**/*) # 清除所有现有规则 page.route(**/*, profiles[profile_name])4.2 真实项目中的最佳实践模块化管理将不同API的Mock处理拆分为独立模块数据工厂使用Faker等库生成逼真的测试数据状态管理维护全局变量来模拟服务端状态变化自动化启用通过环境变量控制Mock的启用# 示例带状态管理的购物车Mock cart_items [] def mock_cart(route, request): if request.url.endswith(/api/cart/items): if request.method GET: route.fulfill(json{items: cart_items}) elif request.method POST: item request.post_data_json() cart_items.append(item) route.fulfill(status201) else: route.continue_()5. 常见问题与解决方案提示当Mock不生效时首先检查URL匹配规则是否准确问题1拦截规则被忽略原因更早注册的路由调用了continue_解决调整路由注册顺序或使用route.fallback()问题2CORS错误原因Mock响应缺少必要headers解决确保包含Access-Control-Allow-Origin等CORS头def mock_with_cors(route, request): route.fulfill( headers{ Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: GET,POST }, json{data: value} )问题3二进制数据乱码原因文本方式处理了二进制响应解决使用base64编码或BytesIO处理def mock_image(route, request): if request.url.endswith(.jpg): with open(mock.jpg, rb) as f: route.fulfill(bodyf.read(), content_typeimage/jpeg) else: route.continue_()在实际项目中我通常会建立一个mock_utils.py文件集中管理各种Mock处理器配合环境变量实现开发/测试环境的无缝切换。当后端API更新时只需修改对应的Mock处理器即可保持前端开发进度不受阻塞。