如何使用Python unittest的mock功能正确模拟类的依赖项
你当前的测试代码中设置mock_data.return_value无法替换get_posts的返回值,测试运行会直接报错,核心原因是mock的目标对象完全错误。
错误原因分析
你已经将Mock后的HttpClient实例注入到了Post类中,Post.get_posts方法调用的是Mock实例的request方法,全程不会触发真实的requests.get逻辑,因此你patch的requests.get完全不会被调用,设置的返回值自然不会生效。
另外setUp方法上的@patch('app.client.HttpClient')也属于冗余代码,你没有用到patch生成的模拟类,直接手动创建了MagicMock实例注入。
正确的测试实现思路
你要测试的是Post类的业务逻辑,只需要模拟依赖的HttpClient.request方法的返回值即可,不需要触碰底层的requests库:
import unittest from unittest.mock import MagicMock from app.data import Post from app.client import HttpClient class TestPost(unittest.TestCase): def setUp(self): # 构造模拟的HttpClient实例,直接注入到Post self.mock_http = MagicMock(autospec=HttpClient) self.mock_post = Post(self.mock_http) def test_get_posts_success(self): # 构造模拟响应,匹配代码中用到的ok属性和json()方法 mock_resp = MagicMock() mock_resp.ok = True mock_resp.json.return_value = { 'postId': 1, 'title': 'My title', 'description': 'Post description' } # 给模拟的request方法设置返回值 self.mock_http.request.return_value = mock_resp resp = self.mock_post.get_posts(1) # 断言返回值符合预期 assert resp['postId'] == 1 # 额外校验request方法被调用时传入的参数正确(可选) self.mock_http.request.assert_called_once_with( method="GET", url="https://jsonplaceholder.typicode.com/posts/1" ) def test_get_posts_failed(self): # 测试请求失败的场景 mock_resp = MagicMock() mock_resp.ok = False mock_resp.status_code = 404 self.mock_http.request.return_value = mock_resp resp = self.mock_post.get_posts(999) assert resp == 404
执行过程说明
- 初始化阶段:手动创建
HttpClient的模拟实例注入到Post类,Post内部持有的client就是该模拟对象,而非真实的HTTP客户端 - 调用被测方法:
self.mock_post.get_posts(1)执行时,内部调用self.client.request,实际是调用模拟对象的方法,直接返回你预先设置的mock_resp,不会发起任何真实网络请求 - 逻辑校验:代码判断
mock_resp.ok的状态,走对应分支返回结果,完成业务逻辑的测试
额外补充
如果你要测试的是HttpClient类本身的逻辑,才需要patchrequests.get/requests.post,验证HttpClient.request方法是否会根据传入参数正确调用对应的requests方法。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

