如何在pytest中用monkeypatch.setattr多次Mock requests.get?
使用pytest的monkeypatch模拟requests.get的多次调用结果
刚好我之前也处理过类似的需求,用monkeypatch配合unittest.mock就能完美实现你要的效果——和mock包的side_effect一样,让每次requests.get调用返回不同的预期结果。先给你修正一下测试代码里的小坑,再一步步讲实现:
首先,你原来的测试代码里调用get_urls(urls)是不对的,因为get_urls定义的是*urls可变参数,需要把元组解包成单独的参数传进去(也就是get_urls(*urls)),不然函数里只会把整个元组当成一个URL来处理,结果长度会是1而不是3,这个细节很容易踩坑。
接下来分两种常用的实现方式:
方式一:用列表指定顺序化的返回结果
这种方式适合你已经知道调用顺序,只想依次返回固定结果的场景:
from my_package import get_urls import requests from unittest.mock import Mock def test_get_urls(monkeypatch): # 为每个URL创建模拟的Response对象,设置好text属性 mock_resp_a = Mock(text="Content from /a") mock_resp_b = Mock(text="Content from /b") mock_resp_c = Mock(text="Content from /c") # 用Mock的side_effect参数,让每次调用requests.get依次返回这三个对象 monkeypatch.setattr( requests, 'get', Mock(side_effect=[mock_resp_a, mock_resp_b, mock_resp_c]) ) urls = ("https://example.com/a", "https://example.com/b", "https://example.com/c") results = get_urls(*urls) # 验证结果 assert len(results) == 3 assert results == ["Content from /a", "Content from /b", "Content from /c"]
方式二:根据URL动态返回结果
如果需要根据传入的URL不同返回对应内容(不管调用顺序),可以给side_effect传一个自定义函数:
from my_package import get_urls import requests from unittest.mock import Mock def test_get_urls_dynamic(monkeypatch): def mock_get(url): # 创建模拟响应对象 mock_resp = Mock() # 根据URL返回对应的文本 url_to_content = { "https://example.com/a": "Content for A", "https://example.com/b": "Content for B", "https://example.com/c": "Content for C" } mock_resp.text = url_to_content.get(url, "Default content") return mock_resp # 替换requests.get为我们的自定义模拟函数 monkeypatch.setattr(requests, 'get', mock_get) urls = ("https://example.com/b", "https://example.com/a", "https://example.com/c") results = get_urls(*urls) assert results == ["Content for B", "Content for A", "Content for C"]
核心原理
monkeypatch.setattr(requests, 'get', ...)的作用是临时替换requests.get这个函数——在当前测试用例的生命周期内,所有对requests.get的调用都会指向我们的模拟实现。而通过Mock(side_effect=...),我们可以控制每次调用的返回值:
- 如果
side_effect是列表,每次调用会依次取出列表中的元素返回; - 如果是函数,每次调用会执行这个函数,把传入的参数传给它,用函数的返回值作为响应。
这样就完全实现了你要的“模拟每次请求的预期返回结果”的需求。
内容的提问来源于stack exchange,提问作者Jack Moody
相关产品推荐
相关产品推荐

