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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:06:02