Python Mock 对象
外观
Python Mock对象[编辑 | 编辑源代码]
Mock对象是Python单元测试中用于模拟真实对象的测试替身(Test Double),属于unittest.mock
模块(Python 3.3+内置)。它允许开发者隔离被测代码的依赖项,从而专注于逻辑验证而非外部服务或复杂组件的实际行为。
核心概念[编辑 | 编辑源代码]
Mock对象的核心特性包括:
- 行为模拟:替代真实对象的方法或属性
- 调用追踪:记录方法被调用的次数、参数等
- 返回值预设:定义被调用时的固定返回
- 副作用模拟:触发异常或动态响应
基本用法[编辑 | 编辑源代码]
from unittest.mock import Mock # 创建Mock对象 mock_obj = Mock() # 设置返回值 mock_obj.method.return_value = 42 print(mock_obj.method()) # 输出: 42 # 验证调用 mock_obj.method.assert_called_once()
高级功能[编辑 | 编辑源代码]
参数匹配[编辑 | 编辑源代码]
使用unittest.mock.ANY
、unittest.mock.call
等进行灵活匹配:
from unittest.mock import ANY, Mock
mock = Mock()
mock.process_data(ANY, keyword='test')
mock.process_data.assert_called_with(ANY, keyword='test')
补丁(Patch)[编辑 | 编辑源代码]
临时替换模块中的对象:
from unittest.mock import patch
def get_data():
return "真实数据"
with patch('__main__.get_data', return_value="模拟数据"):
print(get_data()) # 输出: 模拟数据
实际案例[编辑 | 编辑源代码]
数据库操作测试[编辑 | 编辑源代码]
模拟数据库连接避免真实IO操作:
import unittest.mock import Mock
class DatabaseTest(unittest.TestCase):
def test_user_query(self):
# 创建模拟连接
mock_conn = Mock()
mock_cursor = mock_conn.cursor.return_value
mock_cursor.fetchall.return_value = [('Alice', 25), ('Bob', 30)]
# 注入模拟对象
result = get_users(mock_conn)
self.assertEqual(len(result), 2)
mock_cursor.execute.assert_called_once_with("SELECT * FROM users")
API调用测试[编辑 | 编辑源代码]
模拟网络请求:
import requests
from unittest.mock import patch
def test_api_call():
with patch('requests.get') as mock_get:
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = {'key': 'value'}
response = fetch_data('https://api.example.com')
assert response == {'key': 'value'}
可视化工作流[编辑 | 编辑源代码]
数学表达[编辑 | 编辑源代码]
Mock的调用验证可表示为: 其中表示第i次调用记录
最佳实践[编辑 | 编辑源代码]
- 优先使用
@patch
装饰器保持测试整洁 - 避免过度模拟导致测试与实现耦合
- 结合
spec
参数保持接口一致性 - 对复杂对象考虑使用
MagicMock
常见问题[编辑 | 编辑源代码]
问题 | 解决方案 |
---|---|
模拟不生效 | 检查补丁目标路径是否正确 |
调用验证失败 | 使用call_args_list 调试实际参数
|
副作用未触发 | 确认side_effect 是否被正确赋值
|
通过系统性地使用Mock对象,开发者可以构建快速、稳定且与外部环境隔离的单元测试,这是现代测试驱动开发(TDD)的重要实践。