Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Python中模拟os.listdir来模拟文件和目录?_Python_Unit Testing_Mocking - Fatal编程技术网

如何在Python中模拟os.listdir来模拟文件和目录?

如何在Python中模拟os.listdir来模拟文件和目录?,python,unit-testing,mocking,Python,Unit Testing,Mocking,我有一个专有的存储库格式,我正在尝试开发一个Python模块来处理这些存储库。回购协议格式如下: /home/X/ | + alpha/ | + beta/ | + project.conf 这里,X是一个项目alpha和beta是此项目中的文件夹,它们表示此项目中的组。在本回购协议中,集团是一个容器,它所代表的内容实际上与此问题无关。repoX在其根级别也有文件project.conf就是这样一个文件的例子

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

/home/X/
       |
       + alpha/
       |
       + beta/
       |
       + project.conf
这里,
X
是一个项目
alpha
beta
是此项目中的文件夹,它们表示此项目中的组。在本回购协议中,集团是一个容器,它所代表的内容实际上与此问题无关。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\u listdir.return\u value
视为由文件和目录组成


如何在同一测试中模拟
os.listdir
os.path.isdir
,以便测试将
alpha
beta
视为目录,将
project.conf
视为文件?

当然,这将取决于您使用的
os
函数,但看起来,在
操作系统上
正是您所需要的。(请注意,您可能不需要修补
path
;它的许多函数都是词法函数,不关心实际的文件系统。)

我通过向模拟的
isdir
对象的
side_effect
属性传递一个iterable来实现所需的行为

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:
        with mock.patch('os.path.isdir') as mocked_isdir:
          mocked_listdir.return_value = ['alpha', 'beta', 'project.conf']
          mocked_isdir.side_effect = [True, True, False]
          project.load()
          self.assertEqual(len(project.groups), 2)
关键是
mocked\u isdir.side\u effect=[True,True,False]
行。iterable中的布尔值应该与传递到
mocked\u listdir.return\u value
属性的目录和文件项的顺序相匹配。

您可以使用它,它是一个非常方便的库,用于测试在假文件系统上的操作

如果您使用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()

您对os.listdir所做的任何操作都不会使其他函数认为这些名称是真正的文件和目录
os.listdir
只是说出了一堆名字。我同意@user2357112所说的。项目中是否有alpha和beta目录?如果是这样,您真的不需要模拟
os.path.isdir
。alpha和beta不是项目的一部分。它们是虚拟目录,用于解释此项目处理的存储库的结构。