如何使用side_effect模拟requests.get().url?附代码测试需求
如何用side_effect模拟requests.get().url完成Swapi API调用函数的测试
问题描述
我编写了以下Python函数,用于循环调用Swapi的人物列表API,收集所有请求的URL直到API返回非200状态码。同时编写了测试函数,但需要用side_effect模拟requests.get().url和响应状态码来完成离线测试,避免真实调用API:
from http import HTTPStatus import requests def consuming_api_swapi_index_page(initial_page: int = 1): """Swapi index page.""" check = HTTPStatus.OK results = [] while check == HTTPStatus.OK: response = requests.get( f'https://swapi.dev/api/people/?page={initial_page}' ) results.append(url := response.url) print(url) check = response.status_code initial_page += 1 return results def test_consuming_api_swapi_index_page() -> None: """Test it.""" values = [ 'https://swapi.dev/api/people/?page=1', 'https://swapi.dev/api/people/?page=2', 'https://swapi.dev/api/people/?page=3', 'https://swapi.dev/api/people/?page=4', 'https://swapi.dev/api/people/?page=5', 'https://swapi.dev/api/people/?page=6', 'https://swapi.dev/api/people/?page=7', 'https://swapi.dev/api/people/?page=8', 'https://swapi.dev/api/people/?page=9', 'https://swapi.dev/api/people/?page=10', ] assert consuming_api_swapi_index_page() == values
解决方案
可以通过unittest.mock的patch装饰器结合side_effect来模拟requests.get的返回值,按顺序返回预设的响应对象,控制每个响应的url和status_code,从而让函数按预期执行并终止循环。
修改后的测试代码
from unittest.mock import patch, Mock from http import HTTPStatus # 替换为你的函数所在模块名 from your_module import consuming_api_swapi_index_page def test_consuming_api_swapi_index_page() -> None: """Test the API consuming function with mocked requests.""" expected_urls = [ 'https://swapi.dev/api/people/?page=1', 'https://swapi.dev/api/people/?page=2', 'https://swapi.dev/api/people/?page=3', 'https://swapi.dev/api/people/?page=4', 'https://swapi.dev/api/people/?page=5', 'https://swapi.dev/api/people/?page=6', 'https://swapi.dev/api/people/?page=7', 'https://swapi.dev/api/people/?page=8', 'https://swapi.dev/api/people/?page=9', 'https://swapi.dev/api/people/?page=10', ] # 构建模拟响应列表:前10个返回200状态和对应URL,最后一个返回404终止循环 mock_responses = [] for url in expected_urls: resp = Mock() resp.url = url resp.status_code = HTTPStatus.OK mock_responses.append(resp) # 添加终止循环的非200响应 final_response = Mock() final_response.status_code = HTTPStatus.NOT_FOUND mock_responses.append(final_response) # 模拟requests.get,按顺序返回预设的响应对象 with patch('requests.get', side_effect=mock_responses): result = consuming_api_swapi_index_page() assert result == expected_urls
关键说明
- Mock响应对象:每个
Mock()实例模拟requests.get返回的响应对象,设置url属性匹配预期请求地址,status_code控制循环的执行逻辑。 - side_effect的作用:当
requests.get被调用时,会按mock_responses列表的顺序依次返回每个Mock对象。前10次调用返回200状态,函数会将对应URL加入结果列表并继续循环;第11次调用返回404状态,循环终止。 - 路径正确的patch:
patch('requests.get')需要确保路径正确,如果你的函数是在某个模块中导入requests,则需要patch该模块中的requests.get(比如from mymodule import requests的话,要patchmymodule.requests.get)。
内容的提问来源于stack exchange,提问作者britodfbr
相关产品推荐
相关产品推荐

