Mock là base class; MagicMock mở rộng với magic method support (__len__, __iter__, __enter__...); AsyncMock (Python 3.8+) bắt buộc cho coroutine — dùng sai type thì assert_awaited_once sẽ silently pass dù không được await.
python
from unittest.mock import Mock, MagicMock, AsyncMock, patch
# Mock — basic mock object
mock = Mock()
mock.method() # OK, trả về Mock
mock.method.assert_called_once()
# MagicMock — Mock + magic methods (__len__, __iter__, __enter__ etc.)
magic = MagicMock()
len(magic) # OK, gọi __len__
with magic: # OK, gọi __enter__/__exit__
pass
list(magic) # OK, gọi __iter__
# AsyncMock (Python 3.8+) — cho async functions
async_mock = AsyncMock(return_value={"data": []})
# await async_mock() # OK
# Patch context manager
with patch('mymodule.requests.get') as mock_get:
mock_get.return_value.json.return_value = {'id': 1}
result = fetch_user(1)
mock_get.assert_called_once_with('https://api.com/users/1')
# Patch cho async
with patch('mymodule.send_email', new_callable=AsyncMock) as mock_email:
mock_email.return_value = True
await register_user("test@test.com")
mock_email.assert_awaited_once()
# side_effect — simulate exceptions hay dynamic return values
mock.method.side_effect = ValueError("DB connection failed")
mock.method.side_effect = [1, 2, 3] # Trả về lần lượtMock is the base class; MagicMock extends it with magic method support (__len__, __iter__, __enter__, etc.); AsyncMock (Python 3.8+) is required for await-able coroutines — use the wrong type and assertions like assert_awaited_once will silently pass.
python
# Mock — basic mock
mock = Mock()
mock.method.assert_called_once()
# MagicMock — Mock + magic methods (__len__, __iter__, __enter__, etc.)
magic = MagicMock()
len(magic); with magic: pass; list(magic) # All work
# AsyncMock (3.8+) — for async functions
async_mock = AsyncMock(return_value={"data": []})
# await async_mock() # returns {"data": []}
# patch context manager
with patch('module.func') as mock_func:
mock_func.return_value = 'value'
result = target_function()
# patch async
with patch('module.send_email', new_callable=AsyncMock) as m:
await register_user("test@test.com")
m.assert_awaited_once()
# side_effect
mock.method.side_effect = ValueError("Error")
mock.method.side_effect = [1, 2, 3] # Returns sequentially