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

如何Mock依赖类的方法?——解决测试Creator.do_a_call时Mock Requester.make_request出现的AttributeError问题

解决Mock Requester.make_request时的AttributeError问题

你遇到的问题核心是mock返回的不是requests.Response实例,而是requests-mock的_Matcher对象,所以代码里访问response.status_code时会触发AttributeError。下面我来一步步帮你修正这个问题:

问题根源

你的mocked_make_request方法里用了requests_mock.Mocker.post(),这个方法返回的是一个用于匹配请求的_Matcher对象,而不是我们需要的requests.Response实例。既然已经通过@patch mock了Requester.make_request方法,我们完全不需要再用requests-mock来拦截请求,直接手动构造符合要求的Response对象即可。

修正方案

1. 改写mock方法,返回正确的Response实例

我们直接创建requests.Response对象,设置好需要的属性(比如status_code、响应内容等),这样就能让Creator.do_a_call正常处理返回值:

def mocked_make_request(self, path, method='get', body=None, custom_headers=None):
    # 手动构造Response实例
    response = Response()
    # 设置状态码,根据测试场景调整
    response.status_code = 200
    # 设置响应内容(_content是Response内部存储内容的属性,需要bytes类型)
    response._content = b'{"result": "success"}'
    # 如果需要响应文本,可以直接设置text属性(可选)
    response.text = '{"result": "success"}'
    return response

注意:这里的参数要和原make_request方法的参数完全匹配(原方法参数是path, method, body, custom_headers),之前你的mocked_make_request用了two, three作为参数名,会导致参数不匹配的问题,一定要修正。

2. 修正测试用例

用side_effect的测试

@patch('Requester.Requester.make_request')
def test_do_a_call_side_effect(self, make_request):
    creator = Creator()
    # 将side_effect指向我们的mock方法
    make_request.side_effect = self.mocked_make_request
    response = creator.do_a_call("mock://test.com")
    self.assertEqual(200, response.status_code)

用return_value的测试

@patch('Requester.Requester.make_request')
def test_do_a_call_return_value(self, make_request):
    creator = Creator()
    # 直接返回构造好的Response实例
    mock_response = Response()
    mock_response.status_code = 200
    mock_response._content = b'{"result": "success"}'
    make_request.return_value = mock_response
    response = creator.do_a_call("mock://test.com")
    self.assertEqual(200, response.status_code)

完整修正后的test.py

import unittest
from unittest.mock import patch
from Creator import Creator
from requests import Response
from http import HTTPStatus as status

class CreatorTest(unittest.TestCase):
    def mocked_make_request(self, path, method='get', body=None, custom_headers=None):
        response = Response()
        response.status_code = status.OK
        response._content = b'{"message": "Success"}'
        response.text = '{"message": "Success"}'
        return response

    @patch('Requester.Requester.make_request')
    def test_do_a_call_side_effect(self, make_request):
        creator = Creator()
        make_request.side_effect = self.mocked_make_request
        response = creator.do_a_call("mock://test.com")
        self.assertEqual(status.OK, response.status_code)

    @patch('Requester.Requester.make_request')
    def test_do_a_call_return_value(self, make_request):
        creator = Creator()
        mock_response = Response()
        mock_response.status_code = status.OK
        mock_response._content = b'{"message": "Success"}'
        mock_response.text = '{"message": "Success"}'
        make_request.return_value = mock_response
        response = creator.do_a_call("mock://test.com")
        self.assertEqual(status.OK, response.status_code)

if __name__ == "__main__":
    unittest.main()

额外提示:测试异常场景

如果要测试do_a_call抛出异常的情况(比如状态码不是200或202),只需要构造对应状态码的Response即可:

def test_do_a_call_raises_exception(self):
    with patch('Requester.Requester.make_request') as make_request:
        mock_response = Response()
        mock_response.status_code = status.BAD_REQUEST
        mock_response.text = 'Invalid request'
        make_request.return_value = mock_response
        creator = Creator()
        with self.assertRaises(Exception) as context:
            creator.do_a_call("mock://test.com")
        # 验证异常内容
        self.assertEqual(context.exception.args[0], status.BAD_REQUEST)
        self.assertEqual(context.exception.args[1], 'Invalid request')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 14:49:09