pytest mocker如何为同一流程两次外部调用返回不同mock值
问题原因
你写两个fixture分别patch同一个save_details方法时,后加载的test_201_mock2会完全覆盖前一个fixture的patch配置,相当于最终只有第二个mock生效,不管方法被调用多少次,都会固定返回test_201_mock2里设置的返回值,自然两次拿到的ID重复。
不需要写两个独立的mock fixture,单个mock配置就可以实现按调用顺序返回不同值的需求。
解决方案
使用mock对象的side_effect参数,将需要按调用顺序返回的结果组成列表传入即可:mock被调用时会按顺序依次返回列表中的元素,第一次调用取第一个元素,第二次调用取第二个元素,以此类推。
正确的Mock写法
@pytest.fixture def mock_save_details(mocker): """按调用顺序返回不同的save_details响应""" return mocker.patch( # 注意:此处路径必须替换为**业务代码中导入save_details的实际路径**,不要填方法定义的源路径 "your_biz_module.save_details", side_effect=[ # 第一次调用返回值 ( "201", { "ACK": { "id": "e944126b-db78-4711-9f97-83c2cd1e09a4", } }, ), # 第二次调用返回值 ( "201", { "ACK": { "id": "4758a428-8f33-4dc8-bb64-a500855f9a8c", } }, ) ] )
测试用例调整
测试用例中只需要引入这一个mock fixture即可,不需要同时传入原来的两个mock:
async def test_create_valid_resource_201( mock_save_details, # 其余原有依赖fixture ... ) -> None: """ 测试合法POST请求返回201响应的逻辑 """ # 执行业务测试逻辑 # ... # 可选:校验mock调用次数符合预期 assert mock_save_details.call_count == 2
扩展说明
- 如果需要更多次调用返回不同值,直接按调用顺序往
side_effect的列表中追加对应返回值即可。 - 如果需要模拟某一次调用抛出异常,直接将异常实例放到列表对应位置即可,例如:
side_effect=[第一次正常返回值, TimeoutError("mock请求超时"), 第三次正常返回值] - 禁止对同一个目标重复patch:后执行的patch会直接替换前一个patch生成的mock对象,永远不会出现多个mock同时拦截同一个方法调用的情况。
内容的提问来源于stack exchange,提问作者Mark R
相关产品推荐
相关产品推荐

