如何使用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
相关产品推荐
相关产品推荐

