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

如何使用requests_mock为同一API返回不同响应以测试循环调用?

如何用requests_mock为同一URL返回不同响应以终止循环测试

我正尝试在单元测试中使用requests_mock来测试带有while循环的API调用。为了终止while循环,需要让API返回不同的响应——URL保持不变但参数有变化,但requests_mock默认不区分参数。

待测试函数

def func():    
   response = requests.get(
       url=<url>,
       params={"limit": 1000},
       headers=<headers>
    ).json()
    while "next" in response["info"].keys():
        response =  requests.get(
            url=<url>,
            params={"limit": 1000, "info": response["info"]},
            headers=<headers>
        ).json()

原测试代码

def test_url(requests_mock):
    requests_mock.get(url, json=<response_with_info_key>)

    func()
    data_request = requests_mock.request_history[0]
    assert data_request.query == "limit=1000"

尝试过的无效方法

我曾尝试传入响应列表,但未达到预期效果:

def test_url(requests_mock):
    requests_mock.get(url, json=[<response_with_info_key>, <response_without_info_key>])

    func()
    data_request = requests_mock.request_history[0]
    assert data_request.query == "limit=1000"

核心问题:如何让requests_mock为同一API发送两个不同的响应?


解决方案

方法1:使用side_effect参数返回序列响应

requests_mock的get方法支持side_effect参数,传入响应列表后,每次请求会依次返回列表中的内容,刚好匹配循环的两次请求场景。

修改后的测试代码:

def test_url(requests_mock):
    # 定义两个响应:第一个带"next"触发循环,第二个不带终止循环
    response_with_next = {"info": {"next": "sample_token"}}
    response_without_next = {"info": {}}

    # 通过side_effect按顺序返回响应
    requests_mock.get(url, side_effect=[response_with_next, response_without_next])

    func()

    # 验证两次请求的参数
    first_request = requests_mock.request_history[0]
    assert first_request.query == "limit=1000"

    second_request = requests_mock.request_history[1]
    assert "limit=1000" in second_request.query
    assert "info=sample_token" in second_request.query

方法2:根据请求参数动态返回响应

如果需要更灵活的控制(比如根据请求参数的不同返回对应响应),可以给side_effect传入一个函数,通过解析请求参数来判断返回内容。

示例代码:

def test_url(requests_mock):
    def dynamic_response(request):
        # 解析请求的查询参数
        params = request.qs
        if "info" not in params:
            # 第一次请求(无info参数),返回带next的响应
            return {"info": {"next": "sample_token"}}
        else:
            # 第二次请求(含info参数),返回不带next的响应
            return {"info": {}}

    requests_mock.get(url, json=dynamic_response)

    func()

    # 验证确实发起了两次请求
    assert len(requests_mock.request_history) == 2

注意事项

  • 待测试函数中requests.get的参数缺少逗号(比如url=<url>后需要加逗号),需先修正语法错误才能正常运行。
  • 使用side_effect的列表模式时,要确保列表长度与预期请求次数匹配,超出次数会抛出StopIteration异常。
  • 可通过requests_mock.request_history查看所有请求记录,用于验证请求参数的正确性。

内容的提问来源于stack exchange,提问作者techdoodle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:40:30