[英]Python - Mock requests with side_effect
我正在尝试模拟我的请求。 有副作用。 我想为每个副作用值关联一个不同的 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)
# The func1 is executing multiple API calls using requests.get() and status_code is needed
a = func1(a, b)
assert a == "something"
我一直无法找到一种方法(在文档和 SO 中)为每个模拟请求关联 status_code。
我在想这样的事情,但显然行不通:
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
unittest
(不是pytest
)的可能解决方案我在@baguette 添加真正的函数func1()
之前写了这个答案,所以我创建了一个名为my_file_01.py
的文件,其中包含我的生产函数func1()
:
import requests
def func1():
response1 = 'empty1'
response2 = 'empty2'
r = requests.get('http://www.someurl.com')
if r.status_code == 200:
response1 = r.json()
r = requests.get('http://www.some_other_url.com')
if r.status_code == 500:
response2 = r.error_message
return [response1, response2]
如您所见, func1()
调用requests.get()
两次并检查响应的状态代码。
我已将测试代码插入到具有以下内容的不同文件中:
import unittest
from unittest import mock
from my_file_01 import func1
def request_resp1(url):
response_mock = mock.Mock()
response_mock.status_code = 200
response_mock.json.return_value = {'key1': 'value1'}
return response_mock
def request_resp2(url):
response_mock = mock.Mock()
response_mock.status_code = 500
response_mock.error_message = "Failed"
return response_mock
class TestFunc1(unittest.TestCase):
@mock.patch("my_file_01.requests")
def test_func1(self, mock_requests):
print("test func1()")
mock_requests.get.side_effect = [request_resp1(""), request_resp2("")]
[response1, response2] = func1()
print("response1 = " + str(response1))
print("response2 = " + str(response2))
if __name__ == "__main__":
unittest.main()
测试文件定义了包含测试方法TestFunc1
test_func1()
的测试类 TestFunc1。
此外,在文件中定义了 2 个函数,称为request_resp1()
和request_resp2()
。 这些函数用于定义不同的响应值,以便第一次调用requests.get()
成功 ( status_code = 200
),而第二次调用requests.get()
失败 ( status_code = 500
)。
如果您尝试执行测试代码,您会看到func1()
为响应的 2 个不同的 status_codes 返回不同的值。
基于@frankfalse 的解决方案,这两个模拟函数可以用一个类代替。
class MockResponse:
def __init__(self, json_data, status_code=requests.codes.ok):
self.json_data = json_data
self.status_code = status_code
def json(self):
return self.json_data
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.