python - 如何模拟 os.listdir 以假装 Python 中的文件和目录?

标签 python unit-testing mocking

我有一个专有的存储库格式,我正在尝试开发一个 Python 模块来处理这些存储库。 repo 格式如下:

/home/X/
       |
       + alpha/
       |
       + beta/
       |
       + project.conf

这里,X 是一个项目。 alphabeta 是该项目中的文件夹,它们代表该项目中的group 是这个 repo 中的一个容器,它代表的内容与这个问题无关。 repo X 在其根级别也有文件; project.conf 是此类文件的示例。

我有一个名为 Project 的类,它抽象了诸如 X 之类的项目。 Project 类有一个方法 load() 可以构建内存中的表示形式。

class Project(object):

    def load(self):
        for entry in os.listdir(self.root):
            path = os.path.join(self.root, entry)
            if os.path.isdir(path):
                group = Group(path)
                self.groups.append(group)
                group.load()
            else:
                # process files ...

要通过模拟文件系统对 load() 方法进行单元测试,我有:

import unittest
from unittest import mock
import Project

class TestRepo(unittest.TestCase):

    def test_load_project(self):
        project = Project("X")

        with mock.patch('os.listdir') as mocked_listdir:
            mocked_listdir.return_value = ['alpha', 'beta', 'project.conf']
            project.load()
            self.assertEqual(len(project.groups), 2)

这确实模拟了 os.listdir 成功。但我无法欺骗 Python 将 mocked_listdir.return_value 视为由文件和目录组成。

如何模拟 os.listdiros.path.isdir在同一个测试中,这样测试就会看到alphabeta 作为目录,project.conf 作为文件?

最佳答案

您可以使用 pyfakefs(sourcedocs),这是一个非常方便的库,用于测试假文件系统上的操作。

如果你使用pytest,它有一个插件,所有的文件系统功能都已经打好了补丁,你只需要使用它的fs fixture:

import os

def test_foo(fs):
    fs.CreateFile('/home/x/alpha/1')
    fs.CreateFile('/home/x/beta/2')
    fs.CreateFile('/home/x/p.conf')    
    assert os.listdir('/home/x/')) == ['alpha', 'beta', 'p.conf']

或者如果您更喜欢unittest:

import os
import unittest

from pyfakefs import fake_filesystem_unittest
   
class TestRepo(fake_filesystem_unittest.TestCase):

    def setUp(self):
        self.setUpPyfakefs()

    def test_foo(self):
        os.makedirs('/home/x/alpha')
        os.makedirs('/home/x/beta')
        with open('/home/x/p.conf', 'w') as f:
            f.write('foo')
        self.assertEqual(os.listdir('/home/x/'), ['alpha', 'beta', 'p.conf'])


if __name__ == "__main__":
    unittest.main()

关于python - 如何模拟 os.listdir 以假装 Python 中的文件和目录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46633634/

相关文章:

python - 如何将宽度和高度(以像素为单位)转换为用于 python 库 pyte 的列?

python - 如何使用 Mysql Python 连接器检索二进制数据?

python - 当 `pop` 循环列表时 `for` -ing 元素发生了什么

c# - xunit-如何在单元测试中获取HttpContext.User.Identity

java - 如何在 Java (jUnit4) 中轻松模拟出静态方法

ruby-on-rails - 何时以及何时不 stub /模拟测试

python - 在docker-py中公开网络上的端口

python - 如何在 Eclipse 或命令行中为 Google App Engine 运行 Python 代码覆盖率测试

javascript - 无法在 Jasmine-karma 的 POST 时模拟 $httpbackend

c++ - 哪些模拟框架允许对遗留代码进行零更改?