Python全局类实例打补丁测试断言失败问题排查
Python全局类实例打补丁测试断言失败问题排查
问题场景
我的项目结构如下:
├── core | └── service | └── file.py └── tests └── test_file.py
在file.py里,我定义了一个依赖全局类实例的函数fun:
# file.py from another_module import myClass cls_instance=myClass() def fun(): return cls_instance.request()
我想通过patch来测试这个函数,于是写了test_file.py:
# test_file.py from core.service.file import fun class TestCase(unittest.TestCase): @patch("core.service.file.cls_instance") def setUp(self, mock): self.mock = mock.return_value def test_fun(self): self.mock.request.return_value = 1 resp=fun() self.assertEqual(resp, 1)
但测试失败了,错误信息是:
Expected : None Actual : 1
这到底哪里出错了?
问题分析
你遇到的问题主要出在两个关键点上:
1. Mock对象的赋值逻辑错误
当你用@patch("core.service.file.cls_instance")装饰setUp时,传入的mock参数本身就是被补丁替换后的cls_instance对象,而不是一个用来生成实例的mock工厂。你写的self.mock = mock.return_value完全是画蛇添足——这个return_value是把mock当作可调用对象(比如类)时才会用到的属性,但这里我们补丁的是一个已经实例化好的对象,所以mock.return_value默认是None,直接导致你的self.mock变成了None。
2. setUp上的@patch作用域问题
unittest的@patch装饰器如果用在setUp方法上,补丁只会在setUp方法执行期间生效,当setUp执行完毕,补丁就会被自动撤销。这就导致你在test_fun方法中调用fun()时,实际上用的还是原来的cls_instance,而不是你在setUp里准备的mock对象。
解决方案
这里给你两种正确的写法,任选其一即可:
方案一:直接在测试方法上使用@patch
把补丁直接装饰在测试方法上,这样补丁会在整个测试方法执行期间生效,mock参数也会直接传入测试方法:
from core.service.file import fun import unittest from unittest.mock import patch class TestCase(unittest.TestCase): @patch("core.service.file.cls_instance") def test_fun(self, mock_cls_instance): # 给补丁后的实例的request方法设置返回值 mock_cls_instance.request.return_value = 1 resp = fun() self.assertEqual(resp, 1)
方案二:在setUp/tearDown中手动管理补丁
如果你需要在多个测试方法中复用这个mock,可以用上下文管理器手动启动和停止补丁:
from core.service.file import fun import unittest from unittest.mock import patch class TestCase(unittest.TestCase): def setUp(self): # 启动补丁,获取mock对象 self.patch_instance = patch("core.service.file.cls_instance") self.mock_cls_instance = self.patch_instance.start() def tearDown(self): # 测试结束后停止补丁,恢复原对象 self.patch_instance.stop() def test_fun(self): self.mock_cls_instance.request.return_value = 1 resp = fun() self.assertEqual(resp, 1)
这样修改后,你的测试就能正确断言fun()返回1了。
备注:内容来源于stack exchange,提问作者rhar
相关产品推荐
相关产品推荐

