gpt4 book ai didi

python - 为迭代定制 unittest.mock.mock_open

转载 作者:IT老高 更新时间:2023-10-28 22:25:18 25 4
gpt4 key购买 nike

我应该如何自定义 unittest.mock.mock_open 来处理这段代码?

file: impexpdemo.py
def import_register(register_fn):
with open(register_fn) as f:
return [line for line in f]

我的第一次尝试尝试了 read_data

class TestByteOrderMark1(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']

def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open(read_data=self.TEST_TEXT)
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN)
self.assertEqual(result, self.TEST_TEXT)

这失败了,大概是因为代码没有使用 read、readline 或 readlines。documentation对于 unittest.mock.mock_open 说,“read_data 是文件句柄的 read()、readline() 和 readlines() 方法返回的字符串。对这些方法的调用将从 read_data 获取数据,直到它被耗尽。这些方法的模拟非常简单。如果您需要对提供给测试代码的数据进行更多控制,则需要自己自定义此模拟。默认情况下,read_data 是一个空字符串。"

由于文档没有提示需要什么样的自定义,我尝试了 return_valueside_effect。都没有用。

class TestByteOrderMark2(unittest.TestCase):
REGISTER_FN = 'test_dummy_path'
TEST_TEXT = ['test text 1\n', 'test text 2\n']

def test_byte_order_mark_absent(self):
m = unittest.mock.mock_open()
m().side_effect = self.TEST_TEXT
with unittest.mock.patch('builtins.open', m):
result = impexpdemo.import_register(self.REGISTER_FN)
self.assertEqual(result, self.TEST_TEXT)

最佳答案

mock_open() 对象确实没有实现迭代。

如果您不使用文件对象作为上下文管理器,您可以使用:

m = unittest.mock.MagicMock(name='open', spec=open)
m.return_value = iter(self.TEST_TEXT)

with unittest.mock.patch('builtins.open', m):

现在 open() 返回一个迭代器,它可以像文件对象一样直接迭代,它也可以与 next() 一起使用.但是,它不能用作上下文管理器。

您可以将它与 mock_open() 结合使用,然后在返回值上提供 __iter____next__ 方法,额外的好处是 mock_open() 还添加了用作上下文管理器的先决条件:

# Note: read_data must be a string!
m = unittest.mock.mock_open(read_data=''.join(self.TEST_TEXT))
m.return_value.__iter__ = lambda self: self
m.return_value.__next__ = lambda self: next(iter(self.readline, ''))

这里的返回值是从 file 对象 (Python 2) 或 in-memory file objects 指定的 MagicMock 对象(Python 3),但只有 readwrite__enter__ 方法已被删除。

上述在 Python 2 中不起作用,因为 a) Python 2 期望 next 存在,而不是 __next__ 和 b) next 是不被视为 Mock 中的特殊方法(正确地如此),所以即使您在上面的示例中将 __next__ 重命名为 nexttype返回值不会有 next 方法。对于大多数情况,让文件对象产生一个可迭代而不是一个迭代器就足够了:

# Python 2!
m = mock.mock_open(read_data=''.join(self.TEST_TEXT))
m.return_value.__iter__ = lambda self: iter(self.readline, '')

任何使用 iter(fileobj) 的代码都可以工作(包括 for 循环)。

有一个open issue in the Python tracker旨在弥补这一差距。

关于python - 为迭代定制 unittest.mock.mock_open,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24779893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com