专栏进度:06 / 10 (自动化实战专题)
Mock 的本质是模拟。它通过拦截真实的请求并返回预设的伪造数据,从而断开系统与不稳定依赖(如银行接口、高成本云服务、未完成的微服务)的连接。
一、 Mock 的两大阵地:单体测试 vs 集成测试
- 代码级 Mock(针对单元测试)
在 Python 中,我们使用内置的 unittest.mock 或 pytest-mock 插件。它直接拦截代码中的函数调用。
应用场景:某个函数需要读取磁盘 1GB 文件,我们 Mock 它,直接让它返回一段文本。
- 协议级 Mock(针对接口/UI 自动化)
通过拦截 HTTP 协议来实现。
应用场景:Playwright 拦截浏览器发出的 XHR 请求,或者使用 Mock Server(如 Moco, WireMock)作为代理。
二、 实战 1:使用 pytest-mock 拦截内部函数
安装插件:pip install pytest-mock
假设我们有一个发邮件的业务逻辑,我们不想每次测试都真发邮件:
Python
# business.pydefsend_email(address):# 这是一个耗时且依赖网络的操作print(f"正在给{address}发送真实邮件...")returnTruedefregister_user(user):# 注册逻辑...ifsend_email(user['email']):return"Register Success"Python
# tests/test_mock.pydeftest_register_with_mock(mocker):# 使用 mocker.patch 拦截 send_email 函数mock_send=mocker.patch("business.send_email",return_value=True)user={"name":"Gemini","email":"test@example.com"}result=register_user(user)assertresult=="Register Success"# 验证该函数是否被正确调用过mock_send.assert_called_once_with("test@example.com")三、 实战 2:Playwright 拦截接口(UI 自动化黑科技)
这是 Playwright 吊打 Selenium 的核心功能之一。它可以让浏览器“产生幻觉”。
Python
deftest_mock_api(page):# 拦截特定的 API 请求并返回 Mock 结果page.route("**/api/user/balance",lambdaroute:route.fulfill(status=200,body='{"balance": 9999999.99}',content_type="application/json"))page.goto("https://my-bank.com/profile")# 此时页面显示的余额将直接变为 9999999.99,而无需真的充值assertpage.locator("#balance_val").has_text("9999999.99")四、 什么时候该用 Mock?什么时候不该用?
建议使用 Mock 严禁滥用 Mock
第三方支付、短信网关(收费且不稳定) 被测系统的核心业务逻辑(Mock 了就没测到本质)
后端接口尚未开发完成(前后端并行测试) 涉及到数据库一致性的最终检查
构造极端故障(如:超时、403、502) 已经处于生产环境上线前的最后验收测试
五、 避坑指南:Mock 的“反噬”
Mock 幻觉:如果 Mock 的数据结构与真实接口脱节,你的自动化测试虽然全是绿色(PASS),但上线后会直接崩溃。对策:定期进行“契约测试(Contract Testing)”,确保 Mock 数据与真实接口定义同步。
过度隔离:如果一个用例里 80% 的步骤都是 Mock 的,那么这个测试的真实性将大打折扣。