You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 18:22:28