如何使用request-mock模拟文件下载以测试loader函数?
使用requests-mock测试loader函数的入门指南
核心思路
测试这个loader函数时,我们要隔离所有外部依赖:不用真的发网络请求、不实际创建文件、也不依赖modify_file_name的具体实现,只验证loader本身的逻辑是否正确。需要用到两个工具:requests-mock(拦截网络请求)和Python自带的unittest.mock(mock其他函数/操作)。
第一步:准备环境
先安装必要的库:
pip install pytest requests-mock
(用Python自带的unittest框架的话,无需安装pytest)
第二步:编写测试用例(以unittest为例)
假设你的loader函数在my_module.py里,新建一个test_loader.py文件,代码如下:
import unittest from unittest.mock import patch, mock_open import requests_mock from my_module import loader # 导入你的loader函数 class TestLoader(unittest.TestCase): def test_loader_default_output(self): # 1. 拦截requests.get,模拟返回预设的网页内容 test_link = "https://example.com/test-page" mock_response_text = "<html>测试页面内容</html>" with requests_mock.Mocker() as m: m.get(test_link, text=mock_response_text) # 2. Mock自定义函数modify_file_name,返回固定文件名 with patch('my_module.modify_file_name') as mock_modify: mock_modify.return_value = "test_page" # 3. Mock os.getcwd,返回测试用的当前目录 with patch('os.getcwd') as mock_cwd: test_current_dir = "/tmp/test-dir" mock_cwd.return_value = test_current_dir # 4. Mock文件写入操作,避免真的创建文件 with patch('builtins.open', mock_open()) as mock_file: # 调用loader函数 result_filepath = loader(test_link) # 验证返回的文件路径是否正确 expected_path = f"{test_current_dir}/test_page.html" self.assertEqual(result_filepath, expected_path) # 验证文件是否写入了正确的内容 mock_file().write.assert_called_once_with(mock_response_text) def test_loader_custom_output_dir(self): # 测试指定自定义输出目录的情况 test_link = "https://example.com/another-page" mock_response_text = "<html>另一页面内容</html>" with requests_mock.Mocker() as m: m.get(test_link, text=mock_response_text) with patch('my_module.modify_file_name') as mock_modify: mock_modify.return_value = "another_page" # 指定自定义输出目录 custom_dir = "/tmp/custom-test-dir" with patch('builtins.open', mock_open()) as mock_file: result_filepath = loader(test_link, output=custom_dir) # 验证路径 expected_path = f"{custom_dir}/another_page.html" self.assertEqual(result_filepath, expected_path) # 验证写入内容 mock_file().write.assert_called_once_with(mock_response_text) if __name__ == '__main__': unittest.main()
关键部分解释
- requests_mock.Mocker():上下文管理器,会拦截所有
requests.get调用,用我们预设的text内容作为响应,彻底避免真实网络请求。 - patch('my_module.modify_file_name'):因为我们只测试loader的逻辑,不需要关心
modify_file_name怎么生成文件名,直接mock它返回固定值,确保测试不受这个函数的影响。 - patch('os.getcwd'):默认情况下loader会获取当前工作目录,mock后可以返回我们指定的测试目录,避免依赖真实环境的目录结构。
- patch('builtins.open', mock_open()):模拟文件打开和写入操作,不会在磁盘上创建真实文件,同时可以通过
assert_called_once_with验证写入的内容是否正确。
初学者小提示
- 路径要准确:用
patch时,必须写被mock函数的完整模块路径,比如modify_file_name如果在my_module里,就写patch('my_module.modify_file_name'),不能只写函数名。 - 覆盖所有分支:一定要测试
output参数的两种情况(默认值、自定义目录),确保loader的所有逻辑分支都被验证到。 - 验证行为而非结果:除了检查返回的文件路径,还要验证依赖函数的调用情况(比如
requests.get是否用了正确的链接,write是否传入了正确的响应文本),这样能确保loader的逻辑完全符合预期。
内容的提问来源于stack exchange,提问作者Gvinevra Lodegrance
相关产品推荐
相关产品推荐

