使用Unittest mock模拟读取yaml文件的单元测试问题求助
测试问题修正方案
原测试存在的核心问题
- Mock对象完全错误:待测试函数判断文件存在调用的是
os.path.isfile,你mock的os.listdir没有被函数使用,完全不影响执行逻辑 - 测试方法参数缺失:继承自
unittest.TestCase的测试类的测试方法必须传入self参数,否则用例无法正常执行 - 测试逻辑自相矛盾:两次传入的参数都是不存在的
false-config.yml,同时断言返回None和非None,逻辑完全不成立 - 未覆盖正常读取场景:只测试了文件不存在的分支,没有验证文件存在时的解析返回逻辑
- 依赖未完全隔离:如果不Mock文件读取和yaml解析逻辑,测试会依赖真实磁盘文件,不符合单元测试的隔离要求
修正后的测试代码
from unittest import mock, TestCase from project import fs import yaml from typing import Dict, Optional class TestReadYamlFromCwd(TestCase): # 测试文件不存在的场景 def test_read_yaml_file_not_exist_return_none(self): # mock os.path.isfile返回False,模拟文件不存在 with mock.patch('project.fs.os.path.isfile', return_value=False): val = fs.read_yaml_from_cwd("not-exist.yml") self.assertIsNone(val) # 测试文件存在、正常读取解析的场景 def test_read_yaml_file_exist_return_content(self): # 模拟yaml解析后的返回内容 mock_yaml_content: Dict = {"config_key": "test_val", "enable": True} # 依次mock文件判断、文件读取、yaml解析三个依赖 with mock.patch('project.fs.os.path.isfile', return_value=True), \ mock.patch('project.fs.open', mock.mock_open(read_data="")), \ mock.patch('project.fs.yaml.load', return_value=mock_yaml_content) as mock_load: val: Optional[Dict] = fs.read_yaml_from_cwd("test-config.yml") # 验证返回值符合预期 self.assertEqual(val, mock_yaml_content) # 验证yaml.load使用了正确的SafeLoader参数,避免安全问题 mock_load.assert_called_once_with(mock.ANY, Loader=yaml.SafeLoader)
修改说明
- 替换了Mock对象,直接Mock函数用到的
os.path.isfile,精准控制文件是否存在的判断结果 - 拆分两个测试用例,分别覆盖文件不存在、文件存在两个分支,逻辑清晰
- 补充了文件读取、yaml解析的Mock,完全隔离磁盘IO和第三方库依赖,测试可以独立执行
- 使用unittest自带的断言方法
assertIsNone、assertEqual等,执行报错时提示更清晰 - 增加了对
yaml.load参数的校验,避免Loader参数被误改导致的安全隐患 - 额外提示:原函数的返回类型标注不准确,存在返回None的情况,建议把返回类型改为
Optional[Dict],避免类型检查工具报错
内容的提问来源于stack exchange,提问作者Data Mastery
相关产品推荐
相关产品推荐

