如何在不修改接口的前提下为发起网络请求的函数编写单元测试?
解决方案:通过模拟网络请求实现无依赖单元测试
要在不修改原函数接口、不发起真实网络请求的前提下编写合格的单元测试,核心思路是模拟requests.get的行为,让它返回预先准备好的测试用Zip包内容,而非真实请求网络。以下是具体实现步骤:
1. 准备测试数据
提前创建包含测试用数据的Zip包(比如test_data/test_books.zip),放在测试目录下,确保Zip内的数据结构和真实返回的一致。
2. 使用unittest.mock模拟网络请求
利用Python标准库的unittest.mock.patch,替换原函数中调用的requests.get方法,让它返回包含本地Zip内容的模拟响应对象。
完整测试代码示例
假设你的函数在book_parser.py文件中,测试文件结构如下:
project/ ├── book_parser.py ├── tests/ │ ├── test_data/ │ │ └── test_books.zip │ └── test_book_parser.py
测试代码:
import unittest from unittest.mock import patch, MagicMock import os from book_parser import get_book_objects, Book class TestGetBookObjects(unittest.TestCase): def setUp(self): # 读取本地测试Zip文件的二进制内容 zip_file_path = os.path.join(os.path.dirname(__file__), "test_data", "test_books.zip") with open(zip_file_path, "rb") as f: self.test_zip_content = f.read() @patch("book_parser.requests.get") def test_get_book_objects(self, mock_get): # 配置模拟响应:返回本地Zip内容 mock_response = MagicMock() mock_response.content = self.test_zip_content mock_get.return_value = mock_response # 调用待测试函数 result = get_book_objects("2024-01-01") # 断言结果符合预期(根据你的测试数据调整) self.assertEqual(len(result), 2) self.assertEqual(result[0].title, "Sample Book 1") self.assertEqual(result[1].author, "John Doe") # 验证请求是否被正确触发 mock_get.assert_called_once_with("HTTP-URL-2024-01-01") if __name__ == "__main__": unittest.main()
为什么这符合单元测试要求?
- 无真实网络请求:完全屏蔽了跨网络调用,满足《修改代码的艺术》中单元测试的核心要求
- 不修改原函数接口:测试时直接调用原函数,保持了函数的原有使用方式
- 速度快且稳定:测试依赖本地文件,执行速度快,不受网络环境影响
- 可重复验证:测试数据固定,每次运行测试的输入一致,结果可预期
内容的提问来源于stack exchange,提问作者Visrut
相关产品推荐
相关产品推荐

