如何在 Python 中模拟 os.listdir 来伪装文件和目录? [英] How to mock os.listdir to pretend files and directories in Python?

查看:59
本文介绍了如何在 Python 中模拟 os.listdir 来伪装文件和目录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a proprietary repository format and I'm trying to develop a Python module to process these repositories. Repo format goes as:

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

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

Here, X is a project. alpha and beta are folders inside this project and they represent groups in this project. A group is a container in this repo and what it represents is really not relevant for this question. The repo X also has files in its root level; project.conf is an example of such a file.

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

I have a class called Project that abstracts projects such as X. The Project class has a method load() that builds an in-memory representation.

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() 方法进行单元测试,我有:

To unit test the load() method by mocking the file system, I have:

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 视为由文件和目录组成.

This does mock os.listdir successfully. But I can't trick Python to treat mocked_listdir.return_value as consisting of files and directories.

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

How do I mock either os.listdir or os.path.isdir, in the same test, such that the test will see alpha and beta as directories and project.conf as a file?

推荐答案

我设法通过向模拟的 isdirside_effect 属性传递一个可迭代对象来实现所需的行为对象.

I managed to achieve the desired behavior by passing an iterable to the side_effect attribute of the mocked isdir object.

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_isdir.side_effect = [True, True, False] 行.可迭代对象中的布尔值应与传递给 mocked_listdir.return_value 属性的目录和文件条目的顺序匹配.

The key is the mocked_isdir.side_effect = [True, True, False] line. The boolean values in the iterable should match the order of directory and file entries passed to the mocked_listdir.return_value attribute.

这篇关于如何在 Python 中模拟 os.listdir 来伪装文件和目录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆