0
# Patching System
1
2
Comprehensive patching decorators and context managers for temporarily replacing objects during testing. The patching system provides flexible strategies for dependency injection, object replacement, and test isolation with automatic cleanup.
3
4
## Capabilities
5
6
### Basic Patching
7
8
The main `patch` decorator and context manager for replacing objects during tests.
9
10
```python { .api }
11
def patch(
12
target: str,
13
new=..., # DEFAULT creates MagicMock/AsyncMock
14
spec=None,
15
create: bool = False,
16
spec_set=None,
17
autospec=None,
18
new_callable=None,
19
unsafe: bool = False,
20
**kwargs
21
):
22
"""
23
Temporarily replace an object during testing.
24
25
Parameters:
26
- target: String path to object to patch (e.g., 'module.function')
27
- new: Replacement object (DEFAULT creates appropriate mock)
28
- spec: Specification for created mock
29
- create: Create attribute if it doesn't exist
30
- spec_set: Like spec but restricts mock to only spec attributes
31
- autospec: Automatically create spec from target object
32
- new_callable: Factory for creating replacement object
33
- unsafe: Allow patching built-in or restricted objects
34
- **kwargs: Additional arguments for mock creation
35
36
Returns:
37
Context manager/decorator that yields the replacement object
38
"""
39
```
40
41
Usage examples:
42
43
```python
44
from mock import patch, Mock
45
46
# As decorator
47
@patch('module.function')
48
def test_function(mock_func):
49
mock_func.return_value = "mocked_result"
50
# Test code here
51
mock_func.assert_called_once()
52
53
# As context manager
54
def test_with_context():
55
with patch('module.function') as mock_func:
56
mock_func.return_value = "mocked_result"
57
# Test code here
58
mock_func.assert_called_once()
59
60
# Provide specific replacement
61
@patch('module.function', return_value="specific_result")
62
def test_with_specific_mock(mock_func):
63
# mock_func is configured with return_value
64
pass
65
66
# Create mock with specification
67
@patch('module.MyClass', autospec=True)
68
def test_with_autospec(mock_class):
69
# mock_class has same interface as MyClass
70
instance = mock_class()
71
instance.method.return_value = "test"
72
```
73
74
### Object Patching
75
76
Patch attributes of existing objects.
77
78
```python { .api }
79
def patch.object(
80
target,
81
attribute: str,
82
new=...,
83
spec=None,
84
create: bool = False,
85
spec_set=None,
86
autospec=None,
87
new_callable=None,
88
unsafe: bool = False,
89
**kwargs
90
):
91
"""
92
Patch an attribute of an existing object.
93
94
Parameters:
95
- target: Object containing the attribute to patch
96
- attribute: Name of attribute to patch
97
- Other parameters same as patch()
98
"""
99
```
100
101
Usage example:
102
103
```python
104
import os
105
from mock import patch
106
107
# Patch method of existing object
108
@patch.object(os, 'getcwd', return_value='/fake/path')
109
def test_getcwd(mock_getcwd):
110
assert os.getcwd() == '/fake/path'
111
mock_getcwd.assert_called_once()
112
113
# Patch with context manager
114
def test_patch_object():
115
with patch.object(os.path, 'exists', return_value=True) as mock_exists:
116
assert os.path.exists('/any/path') == True
117
mock_exists.assert_called_once_with('/any/path')
118
```
119
120
### Multiple Patching
121
122
Patch multiple attributes of the same object simultaneously.
123
124
```python { .api }
125
def patch.multiple(
126
target,
127
spec=None,
128
create: bool = False,
129
spec_set=None,
130
autospec=None,
131
new_callable=None,
132
unsafe: bool = False,
133
**kwargs
134
):
135
"""
136
Patch multiple attributes of a target object.
137
138
Parameters:
139
- target: Object to patch
140
- **kwargs: attribute_name=replacement pairs
141
- Other parameters same as patch()
142
143
Returns:
144
Dictionary mapping attribute names to mock objects
145
"""
146
```
147
148
Usage example:
149
150
```python
151
from mock import patch
152
153
# Patch multiple methods
154
@patch.multiple('os', getcwd=Mock(return_value='/fake'), getpid=Mock(return_value=123))
155
def test_multiple_patches(getcwd_mock, getpid_mock):
156
# getcwd_mock and getpid_mock are available
157
assert os.getcwd() == '/fake'
158
assert os.getpid() == 123
159
160
# With context manager - returns dict
161
def test_multiple_context():
162
with patch.multiple('os', getcwd=Mock(return_value='/fake'), getpid=Mock(return_value=123)) as mocks:
163
assert os.getcwd() == '/fake'
164
assert os.getpid() == 123
165
mocks['getcwd'].assert_called_once()
166
mocks['getpid'].assert_called_once()
167
```
168
169
### Patch Management
170
171
```python { .api }
172
def patch.stopall() -> None:
173
"""Stop all active patches created with start() method."""
174
```
175
176
Usage with manual patch management:
177
178
```python
179
from mock import patch
180
181
# Manual patch lifecycle
182
def test_manual_patches():
183
# Start patches manually
184
patch1 = patch('module.func1')
185
patch2 = patch('module.func2')
186
187
mock1 = patch1.start()
188
mock2 = patch2.start()
189
190
try:
191
# Test code here
192
mock1.return_value = "result1"
193
mock2.return_value = "result2"
194
195
# Your test assertions
196
pass
197
finally:
198
# Stop all patches
199
patch.stopall()
200
```
201
202
### Dictionary Patching
203
204
Temporarily modify dictionaries during testing.
205
206
```python { .api }
207
class patch.dict:
208
def __init__(
209
self,
210
in_dict,
211
values=(),
212
clear: bool = False,
213
**kwargs
214
) -> None:
215
"""
216
Temporarily modify a dictionary.
217
218
Parameters:
219
- in_dict: Dictionary to modify
220
- values: Values to set (dict or iterable of key-value pairs)
221
- clear: Clear dictionary before setting values
222
- **kwargs: Additional key-value pairs to set
223
"""
224
225
def __call__(self, func):
226
"""Use as decorator."""
227
228
def __enter__(self):
229
"""Use as context manager."""
230
231
def __exit__(self, *args):
232
"""Context manager cleanup."""
233
234
def start(self) -> None:
235
"""Start dictionary patching."""
236
237
def stop(self) -> None:
238
"""Stop dictionary patching."""
239
```
240
241
Usage examples:
242
243
```python
244
import os
245
from mock import patch
246
247
# Patch environment variables
248
@patch.dict(os.environ, {'TEST_VAR': 'test_value'})
249
def test_env_var():
250
assert os.environ['TEST_VAR'] == 'test_value'
251
252
# Context manager with clear
253
def test_env_clear():
254
with patch.dict(os.environ, {'ONLY_VAR': 'only_value'}, clear=True):
255
# os.environ only contains ONLY_VAR
256
assert os.environ == {'ONLY_VAR': 'only_value'}
257
# Original environment restored
258
259
# Patch custom dictionary
260
my_dict = {'existing': 'value'}
261
262
@patch.dict(my_dict, new_key='new_value')
263
def test_custom_dict():
264
assert my_dict['new_key'] == 'new_value'
265
assert my_dict['existing'] == 'value' # Original key preserved
266
```
267
268
### Advanced Patching Patterns
269
270
```python
271
# Patch with side effect
272
@patch('requests.get')
273
def test_with_side_effect(mock_get):
274
def side_effect(url):
275
if 'success' in url:
276
return Mock(status_code=200, json=lambda: {'data': 'success'})
277
else:
278
return Mock(status_code=404)
279
280
mock_get.side_effect = side_effect
281
282
# Test different responses based on input
283
response = requests.get('http://example.com/success')
284
assert response.status_code == 200
285
286
# Patch class and instance methods
287
@patch('module.MyClass')
288
def test_class_and_instance(mock_class):
289
# Configure class mock
290
mock_instance = Mock()
291
mock_class.return_value = mock_instance
292
mock_instance.method.return_value = "instance_result"
293
294
# Test code
295
obj = module.MyClass()
296
result = obj.method()
297
assert result == "instance_result"
298
299
mock_class.assert_called_once()
300
mock_instance.method.assert_called_once()
301
302
# Nested patching
303
@patch('outer.inner.function')
304
@patch('other.module.function')
305
def test_nested_patches(mock_other, mock_inner):
306
# Order matters - innermost decorator is first parameter
307
mock_inner.return_value = "inner_result"
308
mock_other.return_value = "other_result"
309
```
310
311
## Type Definitions
312
313
```python { .api }
314
# Patch object types (internal implementation details)
315
class _patch:
316
"""Internal patch implementation class."""
317
def __init__(self, getter, attribute: str, new, spec, create: bool, spec_set, autospec, new_callable, kwargs, *, unsafe: bool = False) -> None: ...
318
def __enter__(self): ...
319
def __exit__(self, exc_type, exc_value, traceback) -> None: ...
320
def start(self): ...
321
def stop(self) -> None: ...
322
323
class _patch_dict:
324
"""Internal dictionary patch implementation class."""
325
def __init__(self, in_dict, values=(), clear: bool = False, **kwargs) -> None: ...
326
def __enter__(self): ...
327
def __exit__(self, *args) -> None: ...
328
def start(self) -> None: ...
329
def stop(self) -> None: ...
330
```