1. 单元测试 (`unittest`)
基本概念
- 单元测试:针对代码的最小可测试单元(如函数、类方法)的测试。
- 核心组件:
- `TestCase`:测试用例的基类,每个测试方法需继承此类。
- `assertXxx`:断言方法(如 `assertEqual`, `assertIsNone`)。
- `setUp`/`tearDown`:测试前/后的初始化和清理方法。
示例代码
import unittest
def add(a, b):
return a + b
class TestMath(unittest.TestCase):
def test_add(self):
self.assertEqual(add(2, 3), 5) # 断言 2+3=5
self.assertNotEqual(add(2, 2), 5)
if __name__ == "__main__":
unittest.main()
运行测试
python -m unittest HYPERLINK https://test_module.py normalLink \tdfe -10 \tdlt text \tdlf FromInput \tdsub normalLink \tdkey 4jcugmtest_module.py # 运行单个测试文件
python -m unittest discover # 自动发现并运行所有测试
2. Mock 和 MagicMock
Mock 的作用
- 隔离外部依赖:模拟数据库、API 请求等外部调用,避免真实请求。
- 控制返回值:预设方法的返回值或异常。
- 行为验证:检查方法是否被调用、调用参数是否符合预期。
Mock vs MagicMock
- `Mock`:基础模拟对象,需手动定义属性和方法。
from unittest.mock import Mock
mock = Mock()
mock.some_method.return_value = 42
print(mock.some_method()) # 输出 42
- `MagicMock`:自动创建属性和方法,适合模拟复杂对象。
from unittest.mock import MagicMock
magic_mock = MagicMock()
magic_mock.attr.subattr.method.return_value = "success"
print(magic_mock.attr.subattr.method()) # 输出 "success"
3. `@patch` 装饰器
作用
- 临时替换对象:在测试期间,用 `Mock`/`MagicMock` 对象替换指定模块或类的属性。
- 自动恢复:测试结束后,自动还原被替换的对象。
使用场景
- 模拟函数、类方法、API 请求、文件操作等外部依赖。
示例
from unittest.mock import patch
import requests
def get_user_data(user_id):
response = requests.get(f"https://api.example.com/users/{user_id}")
return response.json()
class TestAPI(unittest.TestCase):
@patch("requests.get") # 替换 requests.get 方法
def test_get_user_data(self, mock_get):
# 配置模拟返回值
mock_get.return_value.json.return_value = {"name": "Alice"}
result = get_user_data(1)
self.assertEqual(result, {"name": "Alice"})
mock_get.assert_called_once_with("https://api.example.com/users/1")
4. 核心功能详解
(1) 模拟返回值 (`return_value`)
mock = Mock()
mock.method.return_value = 100
print(mock.method()) # 输出 100
(2) 模拟异常 (`side_effect`)
mock = Mock()
mock.method.side_effect = ValueError("模拟错误")
try:
mock.method()
except ValueError as e:
print(e) # 输出 "模拟错误"
(3) 验证调用行为
mock = Mock()
mock.method(1, 2, key="value")
mock.method.assert_called_once_with(1, 2, key="value") # 验证调用参数
5. 完整测试示例
被测代码 (`calculator.py`)
class Calculator:
def add(self, a, b):
return a + b
def call_external_api(self):
import requests
response = requests.get("https://api.example.com/data")
return response.status_code
测试代码 (`test_calculator.py`)
import unittest
from unittest.mock import patch, MagicMock
from calculator import Calculator
class TestCalculator(unittest.TestCase):
def test_add(self):
calc = Calculator()
self.assertEqual(calc.add(3, 4), 7)
@patch("calculator.requests.get") # 替换 requests.get
def test_call_external_api(self, mock_get):
mock_response = MagicMock()
mock_response.status_code = 200
mock_get.return_value = mock_response
calc = Calculator()
result = calc.call_external_api()
self.assertEqual(result, 200)
mock_get.assert_called_once_with("https://api.example.com/data")
if __name__ == "__main__":
unittest.main()
6. 关键总结
`unittest` | 提供测试框架,管理测试用例和断言。
`Mock` | 基础模拟对象,需手动定义属性和方法。
`MagicMock` | 自动创建属性和方法,适合模拟复杂对象(如类实例、嵌套属性)。
`@patch` | 替换目标对象为 Mock,支持上下文管理器或装饰器语法。
`return_value` | 定义模拟方法的返回值。
`side_effect` | 定义模拟方法的副作用(如抛出异常或动态返回值)。
6686

被折叠的 条评论
为什么被折叠?



