如何使用Mock修补导入模块的'open'函数
我正在为我写的一个模块编写单元测试。我需要对 open
进行修补,这样当被测试模块里的函数调用 open
时,就会使用一个模拟的版本,而不是实际的 open
。
这段代码可以正常工作,但我觉得它可能会影响其他测试,因为它没有把 open
恢复到原来的状态:
class TestCases(unittest.TestCase):
def test_something(self):
from amodule import bmodule
open_mock = mock.MagicMock(spec=open)
bmodule.__builtins__['open'] = open_mock
read_mock = mock.MagicMock()
open_mock.return_value.__enter__.return_value = read_mock
self.assertTrue(bmodule.some_function())
self.assertEqual(open_mock.call_args_list, ['filename1', 'filename2'])
我该如何使用 mock.patch
来做到这一点呢?
1 个回答
4
与其在 __builtins__
中修改 open
函数,不如直接在 bmodule 里进行修改。这样做的好处是,只有 bmodule 中的函数会使用你修改后的 open
函数。
你可以在 mock 文档 中看到更多详细信息。
你可以通过使用 patch.object
作为上下文管理器来替换你的 open
函数:
from mock import patch
class TestCases(unittest.TestCase):
def test_something(self):
from amodule import bmodule
open_mock = mock.MagicMock(spec=open)
read_mock = mock.MagicMock()
open_mock.return_value.__enter__.return_value = read_mock
with patch.object(bmodule, 'open', open_mock, create=True):
self.assertTrue(bmodule.some_function())
self.assertEqual(open_mock.call_args_list, ['filename1', 'filename2'])
使用 with 语句可以保证,当执行离开 with 块时,修改会被移除。create=True
这个部分是为了让 patch 知道你确实想在 bmodule
的命名空间中创建 open
的绑定。这是一个安全措施,防止人们不小心修改错误的名称,但在你的情况下,这是必要的,因为 open
在 __builtins__
中,而你想把它绑定到 bmodule
中。