如何为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
相关产品推荐
相关产品推荐

