繁体   English   中英

用“ open()”模拟

[英]Mocking “with open()”

我正在尝试对从文件中读取行并对其进行处理的方法进行单元测试。

with open([file_name], 'r') as file_list:
    for line in file_list:
        # Do stuff

我尝试了在其他问题上描述的几种方法,但是似乎没有一种方法适用于此情况。 我不太了解python如何在线上使用文件对象作为迭代对象,它在内部使用file_list.readlines()?

这种方式不起作用:

    with mock.patch('[module_name].open') as mocked_open: # also tried with __builtin__ instead of module_name
        mocked_open.return_value = 'line1\nline2'

我有一个

AttributeError: __exit__

也许因为with语句具有此特殊属性来关闭文件?

此代码使file_list成为MagicMock。 如何在此MagicMock上存储数据以对其进行迭代?

with mock.patch("__builtin__.open", mock.mock_open(read_data="data")) as mock_file:

最好的祝福

mock_open的返回值(直到Python 3.7.1)没有提供有效的__iter__方法,这可能使其不适合测试迭代打开文件对象的代码。

相反,我建议将代码重构为采用已打开的类似文件的对象。 也就是说,代替

def some_method(file_name):
    with open([file_name], 'r') as file_list:
        for line in file_list:
            # Do stuff

...

 some_method(file_name)

写成

def some_method(file_obj):
    for line in file_obj:
        # Do stuff

...

with open(file_name, 'r') as file_obj:
    some_method(file_obj)

这将必须执行IO的功能转换为pure(r)函数,该函数可以简单地遍历任何类似于文件的对象。 要测试它,您无需以任何方式模拟open或访问文件系统; 只需创建一个StringIO对象用作参数即可:

def test_it(self):
    f = StringIO.StringIO("line1\nline2\n")
    some_method(f)

(如果您仍然需要编写和测试类似

def some_wrapper(file_name):
    with open(file_name, 'r') as file_obj:
        some_method(file_obj)

请注意,您不需要进行模拟打开就可以做任何特别的事情。 您需要分别测试some_method ,因此测试some_wrapper唯一需要做的就是验证open的返回值是否传递给some_method 在这种情况下, open可以是没有任何特殊行为的普通旧模拟。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM