Z
ZHANK
测试与工程化

Mock 与单元测试

unittest.mock/MagicMock、patch 替换、副作用、断言调用

Mock 与单元测试

测试不应依赖外部服务——unittest.mock 用假对象替代真实依赖,让测试快速、可重复。

学完本章你将: 掌握 MagicMock、patch 替换、断言调用。


Mock 基础

python
from unittest.mock import Mock

# 创建一个 Mock——任何调用都接受
mock = Mock()
mock.any_method(42)      # 不会报错
mock.another("hello")

# 断言调用
mock.any_method.assert_called_once_with(42)
print(mock.any_method.call_count)  # 1

patch —— 替换依赖

python
from unittest.mock import patch

def get_user_name(user_id):
    # 实际上调用外部 API
    resp = requests.get(f"https://api.example.com/users/{user_id}")
    return resp.json()["name"]

# 测试——替换 requests.get
@patch("module.requests.get")
def test_get_user_name(mock_get):
    mock_get.return_value.json.return_value = {"name": "小明"}

    result = get_user_name(1)
    assert result == "小明"
    mock_get.assert_called_once_with("https://api.example.com/users/1")

MagicMock —— 更智能的 Mock

python
from unittest.mock import MagicMock

# MagicMock 自动实现了 Python 的魔术方法
mock = MagicMock()
len(mock)          # 不报错,返回 0
mock[0] = "hello"  # 支持下标
for x in mock:     # 支持迭代
    pass

side_effect —— 模拟异常或多次不同返回值

python
mock = Mock()
mock.get.side_effect = [
    "第1次结果",
    "第2次结果",
    Exception("第3次出错"),
]
print(mock.get())  # "第1次结果"
print(mock.get())  # "第2次结果"
# mock.get()       # 抛出 Exception