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

如何为Mock的requests.get()设置不同请求对应的status_code?

问题:为多次requests.get()调用Mock不同的status_code和返回值

我尝试mock requests模块的requests.get()方法,想为每次调用设置不同的status_code和对应的返回结果,但目前没成功。

我的测试代码如下:

def test_func1(mocker):
    side_effect = ["Ok",'','','Failed']
    
    # This line should be changed
    fake_resp.status_code = 200
    
    fake_resp = mocker.Mock()
    fake_resp.json = mocker.Mock(side_effect=side_effect)       
    
    mocker.patch("app.main.requests.get", return_value=fake_resp)
        
    # func1 executes multiple API calls using requests.get()
    # and status_code is needed
    a = func1(a, b) 
    
    assert a == "something"

我试过这种写法但无效:

def test_func1(mocker):
    side_effect = [(status_code=200, return="Ok"),
                   (status_code=204, return=""), 
                   (status_code=204, return=""),
                   (status_code=500, return="Failed")]
    ....

编辑补充:被测试的func1()代码:

from datetime import datetime, timedelta
import requests

def func1(days, delta_1):
    """
    days: number of days before first search (80, 25, 3)
    delta_1: number of days for the date range search (40, 20, 15)
    """
    now = datetime.now()
    start_date = now + timedelta(days=days)
    
    # Var to stop loop when price is found
    loop_stop = 0
    
    # Var to stop loop when search date is more than a year later
    delta_time = 0

    price = 0
    departureDate = "n/a"

    # For loop to check prices till one year. 
    while loop_stop == 0 and delta_time < (365 - days):
        date_range = (
            (start_date + timedelta(days=delta_time)).strftime("%Y%m%d")
            + "-"
            + (start_date + timedelta(days=delta_time + (delta_1 / 2))).strftime(
                "%Y%m%d"
            )
        )
        
        # Needs to be mocked
        response = requests.get("fake_url_using_date_range_var")
        
        if response.status_code == 204:
            print("No data found on this data range")
            delta_time += delta_1
        elif response.status_code == 200:
            price = response.json()["XXX"][0]
            departureDate = response.json()["YYY"][0]
            loop_stop = 1
        else:
            raise NameError(
                response.status_code,
                "Error occured while querying API",
                response.json(),
            )
        
    return price, departureDate

func1会多次调用requests.get(),并根据返回的status_code执行不同逻辑。


解决方案

核心思路是为每一次请求创建独立的Mock响应对象,每个对象单独设置status_code和json()方法的返回值,最后把这些对象组成列表作为side_effect传给requests.get的mock,这样每次调用requests.get()就会依次返回这些预定义好的响应。

修改后的测试代码如下:

def test_func1(mocker):
    # 为每次请求创建独立的Mock响应
    resp1 = mocker.Mock()
    resp1.status_code = 200
    resp1.json.return_value = {"XXX": ["Ok"], "YYY": ["20241001"]}  # 匹配func1中取[0]的逻辑

    resp2 = mocker.Mock()
    resp2.status_code = 204
    resp2.json.return_value = ""

    resp3 = mocker.Mock()
    resp3.status_code = 204
    resp3.json.return_value = ""

    resp4 = mocker.Mock()
    resp4.status_code = 500
    resp4.json.return_value = "Failed"

    # 将响应对象列表作为side_effect,每次调用依次返回
    mocker.patch("app.main.requests.get", side_effect=[resp1, resp2, resp3, resp4])

    # 调用被测试函数,传入合适的参数
    price, departure_date = func1(80, 40)
    
    # 根据预期结果断言
    assert price == "Ok"
    assert departure_date == "20241001"

关键说明:

  • 每个resp都是独立的Mock实例,分别设置status_code和json.return_value(直接给json属性赋值Mock或者用return_value都可以,后者更简洁)
  • side_effect接收对象列表时,requests.get()会按顺序返回列表中的每个对象,完美匹配func1中多次调用的场景
  • 注意json()的返回值要和func1中的逻辑匹配:比如func1里取response.json()["XXX"][0],所以返回的字典里XXX对应的值要是一个包含元素的列表

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 11:01:11