You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为接收多文件的Python函数编写单元测试,模拟多个测试文件

Python单元测试模拟多文件入参方案

问题原因

  • 未mock os.path.isfile 方法:函数执行第一步就会校验入参是否为存在的文件,未mock的情况下对任意假文件名都会返回False,直接抛出FileNotFoundError
  • patch对象误用:mock.patch返回的是补丁控制对象,不能直接作为文件路径传入函数,需要自定义假文件名,让mock逻辑按文件名匹配对应返回内容

实现方案

以下是可直接运行的测试代码:

import os
import unittest
from unittest import mock
# 此处替换为你自己的read_files函数导入路径
from your_module import read_files

class ReadFilesTestCase(unittest.TestCase):
    def setUp(self):
        # 自定义三个假文件名作为入参
        self.fake_start_log = "fake_start.log"
        self.fake_end_log = "fake_end.log"
        self.fake_abbr_file = "fake_abbr.txt"
        
        # 定义三个文件对应的测试内容
        self.start_log_content = """SVF2018-05-24_12:02:58.917
NHR2018-05-24_12:02:49.914
"""
        self.end_log_content = """SVF2018-05-24_1:04:11.332
NHR2018-05-24_1:04:02.979
"""
        self.abbr_content = """SVF_Sebastian Vettel_FERRARI
NHR_Nico Hulkenberg_RENAULT
"""
        # 期望的返回结果
        self.expected_result = (
            [('SVF', '2018-05-24_12:02:58.917'), ('NHR', '2018-05-24_12:02:49.914')],
            [('SVF', '2018-05-24_1:04:11.332'), ('NHR', '2018-05-24_1:04:02.979')],
            [['SVF', 'Sebastian Vettel', 'FERRARI'], ['NHR', 'Nico Hulkenberg', 'RENAULT']]
        )

    def test_read_files_normal_case(self):
        # 1. mock os.path.isfile,仅对测试用假文件名返回存在
        with mock.patch.object(os.path, 'isfile') as mock_isfile:
            def isfile_side_effect(path):
                if path in (self.fake_start_log, self.fake_end_log, self.fake_abbr_file):
                    return True
                return os.path.exists(path)
            mock_isfile.side_effect = isfile_side_effect

            # 2. mock open,按文件名返回对应内容,适配按行读取逻辑
            with mock.patch("builtins.open", mock.mock_open()) as mock_open_obj:
                def open_side_effect(path, *args, **kwargs):
                    if path == self.fake_start_log:
                        data = self.start_log_content
                    elif path == self.fake_end_log:
                        data = self.end_log_content
                    elif path == self.fake_abbr_file:
                        data = self.abbr_content
                    else:
                        return open(path, *args, **kwargs)
                    file_obj = mock.mock_open(read_data=data).return_value
                    file_obj.__iter__.side_effect = lambda: iter(data.splitlines())
                    return file_obj
                mock_open_obj.side_effect = open_side_effect

                # 执行断言
                result = read_files(self.fake_start_log, self.fake_end_log, self.fake_abbr_file)
                self.assertEqual(result, self.expected_result)

    def test_file_not_found_error(self):
        with self.assertRaises(FileNotFoundError):
            read_files('a.txt', 'b.txt', 'c.txt')

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

逻辑说明

  • 优先mockos.path.isfile绕过文件存在性校验,仅对测试用的三个假文件名返回存在,不影响其他逻辑
  • 通过side_effect让mock的open方法根据传入的文件名返回对应内容,同时处理多行迭代的适配,保证按行读取的逻辑正常运行
  • 不需要创建真实的测试文件,所有逻辑都在mock中完成,符合单元测试隔离性要求

注:如果原函数中start_lines.pop()是为了去掉文件末尾空行,只需要在self.start_log_content末尾多加一行换行,同步调整期望结果即可。

内容的提问来源于stack exchange,提问作者Gorbatov Nikolay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 17:54:03