如何在Python中Mock函数?现有尝试未成功求解决方案
解决Python中Mock自定义函数的问题
看起来你已经搞定了系统函数(比如os.urandom)的Mock,但在Mock自己项目里的foobar函数时遇到了坎儿。核心问题其实是**patch的目标路径不对**——Mock的关键是要替换掉被测试代码实际使用的那个函数引用,而不是原模块里的定义。
先明确你的测试场景,分情况解决
假设你是想在测试用例中替换foobar的行为,我们分两种常见场景处理:
场景1:测试用例直接调用foobar
如果你的测试代码直接调用了从project导入的foobar,那你需要patch的是当前测试模块中foobar的引用(也就是tests.foobar),代码示例如下:
import unittest from unittest.mock import patch from project import foobar def foobar_mock(): return 'mocked' class TestProject(unittest.TestCase): @patch('tests.foobar', side_effect=foobar_mock) def test_foobar_mocked(self, mock_foobar): result = foobar() self.assertEqual(result, 'mocked') mock_foobar.assert_called_once()
场景2:测试其他调用foobar的函数
假设project.py里还有一个依赖foobar的函数,比如:
# project.py def foobar(): return 'original' def use_foobar(): return foobar()
这时候你要测试use_foobar,就需要patchproject模块内部的foobar引用(也就是project.foobar),代码示例如下:
# tests.py import unittest from unittest.mock import patch from project import use_foobar def foobar_mock(): return 'mocked' class TestProject(unittest.TestCase): @patch('project.foobar', side_effect=foobar_mock) def test_use_foobar(self, mock_foobar): result = use_foobar() self.assertEqual(result, 'mocked') mock_foobar.assert_called_once()
关键原理帮你理解
unittest.mock.patch的本质是替换某个命名空间中的对象,简单总结:
- 如果模块A导入了模块B的函数X,且A的函数调用X,那要mock的是
A.X,而非B.X - 如果是直接测试B模块的X,或者测试代码直接导入X并调用,那要mock的是测试模块中的
X(比如tests.X)
回头看你的原有问题
从你提供的代码片段推测,你可能patch了project.foobar,但测试用例里直接调用的是已经导入到tests模块里的foobar引用——这时候替换的是原模块的函数,但测试代码用的还是导入时的旧引用,所以Mock没生效。调整patch的路径就能解决啦!
内容的提问来源于stack exchange,提问作者Alexey
相关产品推荐
相关产品推荐

