0
# Async Mocking
1
2
Specialized mock class for testing asynchronous code with await-specific assertions and async-aware call tracking. AsyncMock provides comprehensive support for testing coroutines, async context managers, and async iterators with full type safety.
3
4
## Capabilities
5
6
### AsyncMock
7
8
Mock class specifically designed for testing asynchronous code with await tracking and async-specific assertion methods.
9
10
```python { .api }
11
class AsyncMock(Mock):
12
def __init__(self, *args, **kwargs) -> None:
13
"""
14
Create an async mock that can be awaited and tracks await calls.
15
16
Inherits all Mock parameters and adds async-specific functionality.
17
"""
18
19
# Async assertion methods
20
def assert_awaited(self) -> None:
21
"""Assert the mock has been awaited at least once."""
22
23
def assert_awaited_once(self) -> None:
24
"""Assert the mock has been awaited exactly once."""
25
26
def assert_awaited_with(self, *args, **kwargs) -> None:
27
"""Assert the mock was last awaited with specified arguments."""
28
29
def assert_awaited_once_with(self, *args, **kwargs) -> None:
30
"""Assert the mock was awaited exactly once with specified arguments."""
31
32
def assert_any_await(self, *args, **kwargs) -> None:
33
"""Assert the mock was awaited with specified arguments at some point."""
34
35
def assert_has_awaits(self, calls, any_order: bool = False) -> None:
36
"""Assert the mock has been awaited with specified call sequence."""
37
38
def assert_not_awaited(self) -> None:
39
"""Assert the mock has never been awaited."""
40
41
def reset_mock(
42
self,
43
visited=None,
44
*,
45
return_value: bool = False,
46
side_effect: bool = False
47
) -> None:
48
"""Reset mock state including await tracking."""
49
50
# Async state attributes
51
await_count: int # Number of times mock was awaited
52
await_args: call | None # Arguments from last await
53
await_args_list: list[call] # All await arguments
54
55
# Function metadata for better integration
56
__name__: str
57
__defaults__: tuple[Any, ...]
58
__kwdefaults__: dict[str, Any]
59
__annotations__: dict[str, Any] | None
60
```
61
62
Usage examples:
63
64
```python
65
import asyncio
66
from mock import AsyncMock
67
68
# Basic async mock usage
69
async def test_async_function():
70
async_mock = AsyncMock(return_value="async_result")
71
72
# Await the mock
73
result = await async_mock("arg1", key="value")
74
assert result == "async_result"
75
76
# Assert await behavior
77
async_mock.assert_awaited_once_with("arg1", key="value")
78
assert async_mock.await_count == 1
79
80
# Mock async context manager
81
async def test_async_context_manager():
82
async_mock = AsyncMock()
83
async_mock.__aenter__.return_value = "context_value"
84
async_mock.__aexit__.return_value = None
85
86
async with async_mock as ctx:
87
assert ctx == "context_value"
88
89
async_mock.__aenter__.assert_awaited_once()
90
async_mock.__aexit__.assert_awaited_once()
91
92
# Mock async iterator
93
async def test_async_iterator():
94
async_mock = AsyncMock()
95
async_mock.__aiter__.return_value = async_mock
96
async_mock.__anext__.side_effect = ["item1", "item2", StopAsyncIteration]
97
98
items = []
99
async for item in async_mock:
100
items.append(item)
101
102
assert items == ["item1", "item2"]
103
async_mock.__aiter__.assert_called_once()
104
```
105
106
### Async Side Effects
107
108
AsyncMock supports both synchronous and asynchronous side effects:
109
110
```python
111
# Async side effect function
112
async def async_side_effect(*args, **kwargs):
113
await asyncio.sleep(0.1)
114
return f"processed: {args}"
115
116
async_mock = AsyncMock(side_effect=async_side_effect)
117
result = await async_mock("test")
118
assert result == "processed: ('test',)"
119
120
# Exception side effect
121
async_mock = AsyncMock(side_effect=ValueError("async error"))
122
try:
123
await async_mock()
124
except ValueError as e:
125
assert str(e) == "async error"
126
127
# Multiple return values
128
async_mock = AsyncMock(side_effect=["first", "second", "third"])
129
assert await async_mock() == "first"
130
assert await async_mock() == "second"
131
assert await async_mock() == "third"
132
```
133
134
### Patching Async Functions
135
136
AsyncMock integrates seamlessly with the patching system:
137
138
```python
139
from mock import patch, AsyncMock
140
141
# Patch async function
142
@patch('module.async_function', new_callable=AsyncMock)
143
async def test_with_async_patch(mock_async_func):
144
mock_async_func.return_value = "mocked_result"
145
146
# Test code that calls module.async_function
147
result = await module.async_function("arg")
148
assert result == "mocked_result"
149
mock_async_func.assert_awaited_once_with("arg")
150
151
# Context manager patching
152
async def test_with_context_patch():
153
with patch('module.async_function', new_callable=AsyncMock) as mock_func:
154
mock_func.return_value = "mocked"
155
result = await module.async_function()
156
assert result == "mocked"
157
```
158
159
### Async Mock Specifications
160
161
AsyncMock supports specification-based mocking for async objects:
162
163
```python
164
class AsyncService:
165
async def fetch_data(self, query: str) -> dict:
166
# Real implementation
167
pass
168
169
async def process_data(self, data: dict) -> str:
170
# Real implementation
171
pass
172
173
# Create mock with async specification
174
async_service_mock = AsyncMock(spec=AsyncService)
175
async_service_mock.fetch_data.return_value = {"result": "data"}
176
async_service_mock.process_data.return_value = "processed"
177
178
# Use the mock
179
data = await async_service_mock.fetch_data("query")
180
result = await async_service_mock.process_data(data)
181
182
async_service_mock.fetch_data.assert_awaited_once_with("query")
183
async_service_mock.process_data.assert_awaited_once_with({"result": "data"})
184
```
185
186
## Type Definitions
187
188
```python { .api }
189
# Async-specific call tracking extends regular call functionality
190
# call objects work the same for both sync and async contexts
191
192
# Coroutine function type checking (from backports)
193
def iscoroutinefunction(func) -> bool:
194
"""Check if a function is a coroutine function."""
195
196
# Async test case base class (from backports)
197
class IsolatedAsyncioTestCase:
198
"""Base class for async test cases with isolated event loops."""
199
```