Python单元测试执行时如何模拟HTTP调用并按实际流程返回响应
解决方案
方法1:直接使用Python标准库unittest.mock.patch(最适配你的代码结构)
你当前的代码所有HTTP请求最终都走HTTPRequestUtils.__get_response这个封装方法,直接patch该方法就能实现根据不同URL返回不同模拟响应的需求,返回的响应会完全按照原有逻辑进入后续的process_response、more_processings处理流程,不会影响业务逻辑执行。
示例代码如下:
from unittest.mock import patch, MagicMock from django.test import TestCase from your_app.module import get_processed_data class TestGetProcessedData(TestCase): def test_different_url_return_different_response(self): # 定义不同URL对应的模拟响应规则 def mock_get_response_side_effect(url, *args, **kwargs): mock_resp = MagicMock() if url == "https://api.service1.com/data": mock_resp.status_code = 200 mock_resp.json.return_value = {"code": 0, "data": {"user_id": 123}} elif url == "https://api.service2.com/export": mock_resp.status_code = 200 mock_resp.json.return_value = {"code": 0, "data": {"file_url": "test.pdf"}} else: mock_resp.status_code = 404 mock_resp.json.return_value = {"code": 404, "msg": "not found"} return mock_resp # patch你封装的HTTP请求方法 with patch("your_app.utils.HTTPRequestUtils.__get_response", side_effect=mock_get_response_side_effect): # 直接调用原业务函数,后续处理逻辑会正常执行 result1 = get_processed_data("https://api.service1.com/data", {}, "tenant1", "req1") # 对最终处理结果做断言即可 self.assertEqual(result1.get("user_id"), 123) result2 = get_processed_data("https://api.service2.com/export", {}, "tenant1", "req2") self.assertEqual(result2.get("file_url"), "test.pdf")
方法2:使用responses库(你此前对它的功能存在误解)
responses库并不是只能测试API调用本身,它的核心作用是拦截所有requests库发出的真实HTTP请求,返回你预设的模拟响应,之后的所有业务处理逻辑都会正常执行,完全符合你的需求。
示例代码如下:
import responses from django.test import TestCase from your_app.module import get_processed_data class TestGetProcessedData(TestCase): @responses.activate def test_different_url_response(self): # 给不同的请求URL注册对应的模拟返回值 responses.add( responses.POST, "https://api.service1.com/data", json={"code": 0, "data": {"user_id": 123}}, status=200 ) responses.add( responses.POST, "https://api.service2.com/export", json={"code": 0, "data": {"file_url": "test.pdf"}}, status=200 ) # 正常调用业务函数,所有后续处理流程会正常执行 result1 = get_processed_data("https://api.service1.com/data", {}, "tenant1", "req1") self.assertEqual(result1.get("user_id"), 123) result2 = get_processed_data("https://api.service2.com/export", {}, "tenant1", "req2") self.assertEqual(result2.get("file_url"), "test.pdf") # 额外可以验证请求参数、请求次数是否符合预期 self.assertEqual(len(responses.calls), 2) self.assertEqual(responses.calls[0].request.url, "https://api.service1.com/data")
该方案适合你不想依赖内部封装方法、想要更贴近真实请求流程的测试场景。
方法3:使用pytest-mock(若你使用pytest作为测试框架)
如果项目使用pytest做单元测试,安装pytest-mock插件后可以简化patch的写法,核心逻辑和方法1完全一致。
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

