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

如何创建带返回类属性方法的mock.Mock对象实现requests.get打桩

问题背景

我希望对requests.get进行patch打桩,让测试逻辑不依赖网络连接,要求模拟方法返回携带合法json数据与状态码的Response对象。我最初编写的模拟函数中定义了包含全部所需能力的MockResponse类(即测试代码中被注释的部分),该方案可正常运行、符合预期。

但pylint提示该类仅包含一个公共方法,我尝试通过mock.Mock创建模拟对象来消除该警告,却始终无法正常运行,核心疑问是:是否可以不定义这类小型自定义类就完成该模拟逻辑?

补充说明:

  • 后续Waket Zheng优化了WebTools代码,新增了属性方法ok需要模拟,此时自定义MockResponse类包含2个方法,pylint警告已不再出现。
  • TLDR:问题下的现有编辑内容提供了一种替代方案,但并未解答我最初提出的核心问题。

相关代码

测试代码

class TestWebtools(TestCase):
    VALID_TEST_CASES = [
        ('https://testurl.com/simple.json', {"value": "someValue"}, "someValue"),
        ('https://testurl.com/valueDoesNotExist.json', {}, ""),
        ('https://testurl.com/error1', None, ""),
    ]

    def _mocked_requests_get(*args, **_):
        # class MockResponse:
        #     def __init__(self, json_data, status_code):
        #         self.json_data = json_data
        #         self.status_code = status_code
        #
        #     def json(self):
        #         return self.json_data
        #
        #     @property
        #     def ok(self):
        #         return self.status_code == 200

        MockResponse = mock.Mock()
        MockResponse.json.return_value = MockResponse.json_data

        for url, value, _ in TestWebtools.VALID_TEST_CASES:
            if args[0] == url:
                return MockResponse(json_data=value, status_code=200)

        return MockResponse(json_data=None, status_code=404)

    @mock.patch('requests.get', _mocked_requests_get)
    def test_download_json(self):
        for url, expected, _ in self.VALID_TEST_CASES:
            self.assertEqual(expected, download_json(url))

被测WebTools代码

def download_json(fromUrl: str) -> Optional[dict]:
    response = requests.get(fromUrl, timeout=5)
    if response.ok:
        return response.json()
    return None
解决方案

完全可以不定义自定义类,直接用mock.Mock实现模拟逻辑。之前的写法无法运行的核心原因是:MockResponse = mock.Mock()创建的是一个Mock实例,不是Mock类,给这个外层实例提前设置的json.return_value属性,不会自动绑定到调用该实例时返回的新子Mock对象上,同时也没有配置ok属性的返回值,自然会运行失败。

正确的实现方式是,每次匹配到请求url时,直接创建新的Mock响应实例,单独给该实例配置需要的属性和方法即可,示例代码如下:

def _mocked_requests_get(*args, **_):
    for url, value, _ in TestWebtools.VALID_TEST_CASES:
        if args[0] == url:
            mock_resp = mock.Mock(status_code=200)
            mock_resp.json.return_value = value
            mock_resp.ok = True
            return mock_resp
    # 匹配不到url时返回404响应
    mock_resp = mock.Mock(status_code=404)
    mock_resp.json.return_value = None
    mock_resp.ok = False
    return mock_resp

如果希望ok属性和status_code自动联动,和真实requests.Response逻辑保持一致,可以用PropertyMock实现动态属性计算,不需要手动指定ok的布尔值:

def _mocked_requests_get(*args, **_):
    for url, value, _ in TestWebtools.VALID_TEST_CASES:
        if args[0] == url:
            mock_resp = mock.Mock(status_code=200)
            mock_resp.json.return_value = value
            # ok属性随status_code动态变化
            type(mock_resp).ok = mock.PropertyMock(side_effect=lambda: mock_resp.status_code == 200)
            return mock_resp
    mock_resp = mock.Mock(status_code=404)
    mock_resp.json.return_value = None
    type(mock_resp).ok = mock.PropertyMock(side_effect=lambda: mock_resp.status_code == 200)
    return mock_resp

以上两种写法都不需要自定义类,完全满足测试需求,也不会触发pylint的相关警告。


内容的提问来源于stack exchange,提问作者lukstru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 08:06:18