Unittest 模拟用 mock 读取 yaml 文件

Unittest simulate reading a yaml file with a mock

我尝试测试一个读取文件和 returns 文件内容的函数,或者 returns none 如果找不到文件。

def read_yaml_from_cwd(file: str) -> Dict:
    """[reads a yaml file from current working directory]
    Args:
        file ([type]): [.yaml or .yml file]
    Returns:
        [type]: [Dictionary]
    """
    path = os.path.join(Path.cwd().resolve(), file)
    if os.path.isfile(path):
        with open(path) as f:
            content = yaml.load(f, Loader=SafeLoader)
            return content
    else:
        return None

这是我的测试:

from unittest import mock, TestCase
from project import fs

class TextExamples(TestCase):

    def test_read_yaml_from_cwd():
        with mock.patch('os.listdir') as mocked_listdir:
            mocked_listdir.return_value = ['test-config.yml']
            val = fs.read_yaml_from_cwd("false-config.yml")
            assert val == None
            val2 = fs.read_yaml_from_cwd("false-config.yml")
            assert val2 != None

我想我从根本上说这些测试和这些模拟所做的事情是错误的。有人可以帮我解决这个问题吗?

测试这个的一种可能性是同时修补 os.path.isfileopen。要修补打开,已经有一个特殊的模拟函数 mock_open,它使您可以设置模拟文件的内容。这意味着您不必模拟 yaml.load,因为这将 return 模拟文件内容。这可能看起来像:

from unittest import mock, TestCase
from unittest.mock import mock_open

class YamlTest(TestCase):

    @mock.patch("builtins.open", mock_open(read_data="data"))
    @mock.patch("os.path.isfile")
    def test_read_yaml_from_cwd(self, patched_isfile):
        # valid file case
        patched_isfile.return_value = True
        result = read_yaml_from_cwd("some_file.yaml")
        self.assertEqual("data", result)

        # invalid file case
        patched_isfile.return_value = False
        result = read_yaml_from_cwd("some_file.yaml")
        self.assertEqual(None, result)

在这种情况下,如果您传递一个有效的文件名,您将测试函数 return 的文件内容,如果您传递一个无效的文件名,则测试 None 函数,这可能是您想要测试的全部内容这里。

为了完整起见,并且因为我在评论中提到了它:使用 pyfakefs 代替会将文件系统替换为假文件系统,您可以像处理真实文件系统一样处理它,在这种情况下它看起来喜欢:

from pyfakefs import fake_filesystem_unittest

class YamlTest(fake_filesystem_unittest.TestCase):

    def setUp(self) -> None:
        self.setUpPyfakefs()
        self.fs.create_file("some_file.yaml", contents="data")

    def test_read_yaml_from_cwd(self):
        # valid file case
        result = read_yaml_from_cwd("some_file.yaml")
        self.assertEqual("data", result)

        # invalid file case
        result = read_yaml_from_cwd("non_existing.yaml")
        self.assertEqual(None, result)

如果您有许多与文件系统相关的测试,这很有意义,但在您的情况下,这可能有点过头了。

免责声明:我是 pyfakefs 的贡献者。