Pytest使用monkeypatch模拟API调用时如何根据不同输入返回不同响应
解决方案
核心问题原因
- 你之前的代码在调用
monkeypatch.setattr时,直接执行了mock_res(data_entry),把函数返回值传给了被mock的get_data,而monkeypatch.setattr要求第三个参数传入可调用对象,这是代码不生效的核心原因。 - MockResponse的结构可以根据实际需求简化,不需要额外嵌套静态方法也能实现需求。
实现方案
方案1:根据被mock函数的入参自动返回对应响应
如果你的api_funct.get_data调用时的入参可以和要返回的value_1、value_2一一对应,直接让mock函数判断入参返回对应值即可:
import pytest from xxx import api_funct # 导入你实际的api模块 value_1 = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'} value_2 = {'key11': 'value11', 'key22': 'value22', 'key33': 'value33'} # 模拟响应对象,如果你原get_data返回的是响应对象需要调用.json()就保留,不需要的话可以直接返回字典 class MockResponse: def __init__(self, json_data): self._json_data = json_data def json(self): return self._json_data def test_dynamic_response(monkeypatch): def mock_get_data(*args, **kwargs): # 这里args是get_data调用时的位置参数,kwargs是关键字参数,根据实际入参判断返回值 # 举个例子:如果调用get_data("type1")就返回value_1,调用get_data("type2")返回value_2 if args[0] == "type1": return MockResponse(value_1) elif args[0] == "type2": return MockResponse(value_2) else: return MockResponse(load_data("total_res.json")) monkeypatch.setattr(api_funct, "get_data", mock_get_data) # 接下来写你的测试逻辑即可,不同入参调用get_data会返回对应响应
方案2:for循环遍历测试场景,动态设置mock返回值
如果你是在参数化测试/for循环里,每个测试场景固定返回某个值,可以用闭包生成对应的mock函数:
def test_loop_response(monkeypatch): # 你的测试场景列表:(入参, 预期返回值) test_cases = [ ("input1", value_1), ("input2", value_2), ("default_input", load_data("total_res.json")) ] for input_param, expect_res in test_cases: # 生成当前场景对应的mock函数 def mock_get_data(*args, **kwargs): return MockResponse(expect_res) monkeypatch.setattr(api_funct, "get_data", mock_get_data) # 执行当前场景的测试逻辑 result = 你要测试的函数(input_param) # 这里写断言逻辑 assert ...
快速修复你原来的写法
如果要保留你原来的代码结构,只要改setattr的部分即可,把直接调用改成传闭包:
data_entry = "value_1" # 你需要的响应类型 # 用闭包捕获当前的data_entry变量 def mock_res(*args, **kwargs): return MockResponse().json(data_entry) monkeypatch.setattr(api_funct, "get_data", mock_res)
内容的提问来源于stack exchange,提问作者hungry_in_learning
相关产品推荐
相关产品推荐

