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

如何使用pytest测试_fetch_files的异常分支而不调用真实FTP服务器

不调用真实FTP服务测试_fetch_files异常分支的方案

现有测试的问题

你当前编写的测试用例存在3个核心错误,无法验证目标逻辑:

  • 直接mock了待测试的_fetch_files本身,完全不会执行实际的函数逻辑,属于无效测试
  • 原函数内部已经捕获ftplib.error_perm异常仅打印错误日志,不会向外抛出异常,使用pytest.raises(Exception)的逻辑不成立
  • 原函数声明返回值为None,断言返回值等于'123.gz not found'本身就不可能成立

正确实现思路

我们只需要mockftplib.FTP类即可模拟所有FTP操作的异常场景,全程不需要发起真实网络请求:
针对你要测试的文件不存在触发异常分支的场景,只需让mock出来的FTP实例的retrbinary方法抛出ftplib.error_perm异常,再验证异常处理逻辑是否符合预期即可。

测试代码示例

import ftplib
import pytest
from unittest import mock
# 导入你自己的函数
from module_three.utils_IO_bound import _fetch_files

def test_fetch_files_file_not_found(tmp_path, caplog):
    tmp_dir_path = tmp_path / 'sub'
    tmp_dir_path.mkdir()
    # 注意patch路径替换为你代码中导入ftplib的对应路径
    with mock.patch("module_three.utils_IO_bound.ftplib.FTP") as mock_ftp_cls:
        # 获取mock出来的FTP实例
        mock_ftp_instance = mock_ftp_cls.return_value.__enter__.return_value
        # 模拟retrbinary方法抛出文件不存在的error_perm异常
        mock_ftp_instance.retrbinary.side_effect = ftplib.error_perm("550 File not found")

        # 执行待测试函数,不会抛出异常
        _fetch_files('ftp.ncdc.noaa.gov', 'pub/data/noaa/2016', '123.gz', tmp_dir_path)

        # 验证FTP的方法调用符合预期
        mock_ftp_cls.assert_called_once_with('ftp.ncdc.noaa.gov', timeout=3.0)
        mock_ftp_instance.login.assert_called_once()
        mock_ftp_instance.cwd.assert_called_once_with('pub/data/noaa/2016')
        mock_ftp_instance.retrbinary.assert_called_once_with('RETR 123.gz', mock.ANY)
        # 验证错误日志正常打印
        assert "123.gz not found" in caplog.text

扩展测试场景

你也可以用同样的思路覆盖其他异常分支:

  • 模拟login()方法抛出异常,测试登录失败的处理逻辑
  • 模拟cwd()方法抛出异常,测试目录切换失败的处理逻辑
  • 模拟FTP连接超时,测试超时场景的处理逻辑

内容的提问来源于stack exchange,提问作者Jeff Varela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 19:51:01