0
# Utilities
1
2
Helper functions and specialized mock classes for common testing scenarios. These utilities provide enhanced functionality for automatic spec creation, file mocking, property mocking, and mock validation to streamline test development.
3
4
## Capabilities
5
6
### Automatic Specification
7
8
Automatically create mocks that match the interface of target objects.
9
10
```python { .api }
11
def create_autospec(
12
spec,
13
spec_set: bool = False,
14
instance: bool = False,
15
_parent=None,
16
_name=None,
17
*,
18
unsafe: bool = False,
19
**kwargs
20
):
21
"""
22
Create a mock with automatic specification based on another object.
23
24
Parameters:
25
- spec: Object to create specification from
26
- spec_set: If True, attempting to access non-existent attributes raises AttributeError
27
- instance: If True, mock represents an instance rather than the class itself
28
- unsafe: Allow mocking of built-in types and methods
29
- **kwargs: Additional arguments passed to Mock constructor
30
31
Returns:
32
Mock object that matches the interface of spec
33
"""
34
```
35
36
Usage examples:
37
38
```python
39
from mock import create_autospec
40
41
class Calculator:
42
def add(self, a: int, b: int) -> int:
43
return a + b
44
45
def multiply(self, a: int, b: int) -> int:
46
return a * b
47
48
# Create mock with automatic spec
49
calc_mock = create_autospec(Calculator, spec_set=True)
50
51
# Mock has same interface as Calculator
52
calc_mock.add.return_value = 10
53
result = calc_mock.add(5, 3)
54
assert result == 10
55
56
# Accessing non-existent method raises AttributeError (with spec_set=True)
57
try:
58
calc_mock.nonexistent_method()
59
except AttributeError:
60
pass # Expected behavior
61
62
# Create instance mock
63
calc_instance_mock = create_autospec(Calculator, instance=True)
64
calc_instance_mock.add.return_value = 15
65
assert calc_instance_mock.add(7, 8) == 15
66
67
# Function autospec
68
def original_function(x: int, y: str = "default") -> str:
69
return f"{y}: {x}"
70
71
func_mock = create_autospec(original_function)
72
func_mock.return_value = "mocked result"
73
result = func_mock(42, y="test")
74
assert result == "mocked result"
75
func_mock.assert_called_once_with(42, y="test")
76
```
77
78
### File Mocking
79
80
Create mock file-like objects for testing file operations.
81
82
```python { .api }
83
def mock_open(mock=None, read_data: str = ""):
84
"""
85
Create a mock that simulates file operations.
86
87
Parameters:
88
- mock: Existing mock to configure (creates new MagicMock if None)
89
- read_data: String data that read() and readline() methods will return
90
91
Returns:
92
Mock object that behaves like a file
93
"""
94
```
95
96
Usage examples:
97
98
```python
99
from mock import mock_open, patch
100
101
# Basic file mocking
102
def test_file_reading():
103
with patch('builtins.open', mock_open(read_data="file content")) as mock_file:
104
with open('test.txt', 'r') as f:
105
content = f.read()
106
107
assert content == "file content"
108
mock_file.assert_called_once_with('test.txt', 'r')
109
110
# Multi-line file content
111
def test_multiline_file():
112
file_content = "line 1\nline 2\nline 3"
113
with patch('builtins.open', mock_open(read_data=file_content)):
114
with open('test.txt', 'r') as f:
115
lines = f.readlines()
116
117
assert lines == ["line 1\n", "line 2\n", "line 3"]
118
119
# Test file writing
120
def test_file_writing():
121
with patch('builtins.open', mock_open()) as mock_file:
122
with open('test.txt', 'w') as f:
123
f.write("test content")
124
125
mock_file.assert_called_once_with('test.txt', 'w')
126
mock_file().write.assert_called_once_with("test content")
127
128
# Complex file operations
129
def test_file_operations():
130
mock_file_data = mock_open(read_data="initial content")
131
132
with patch('builtins.open', mock_file_data):
133
# Test reading
134
with open('file.txt', 'r') as f:
135
content = f.read()
136
assert content == "initial content"
137
138
# Test writing
139
with open('file.txt', 'w') as f:
140
f.write("new content")
141
142
# Verify calls
143
mock_file_data.assert_any_call('file.txt', 'r')
144
mock_file_data.assert_any_call('file.txt', 'w')
145
```
146
147
### Property Mocking
148
149
Mock property attributes and descriptors.
150
151
```python { .api }
152
class PropertyMock(Mock):
153
def __init__(self, *args, **kwargs) -> None:
154
"""Create a mock for property objects."""
155
156
def __get__(self, obj, obj_type=None):
157
"""Descriptor get method - called when property is accessed."""
158
159
def __set__(self, obj, value) -> None:
160
"""Descriptor set method - called when property is assigned."""
161
```
162
163
Usage examples:
164
165
```python
166
from mock import PropertyMock, patch
167
168
class MyClass:
169
@property
170
def value(self):
171
return self._value
172
173
@value.setter
174
def value(self, val):
175
self._value = val
176
177
# Mock property directly
178
def test_property_mock():
179
obj = MyClass()
180
181
with patch.object(MyClass, 'value', new_callable=PropertyMock) as mock_prop:
182
mock_prop.return_value = "mocked_value"
183
184
# Test property access
185
assert obj.value == "mocked_value"
186
mock_prop.__get__.assert_called_once()
187
188
# Test property assignment
189
obj.value = "new_value"
190
mock_prop.__set__.assert_called_once_with(obj, "new_value")
191
192
# Property with side effects
193
def test_property_side_effect():
194
obj = MyClass()
195
196
with patch.object(MyClass, 'value', new_callable=PropertyMock) as mock_prop:
197
# Different behavior on successive calls
198
mock_prop.side_effect = ["first", "second", "third"]
199
200
assert obj.value == "first"
201
assert obj.value == "second"
202
assert obj.value == "third"
203
204
# Mock computed property
205
class ComputedClass:
206
@property
207
def computed(self):
208
return len(self.data) * 2
209
210
def test_computed_property():
211
obj = ComputedClass()
212
213
with patch.object(ComputedClass, 'computed', new_callable=PropertyMock) as mock_prop:
214
mock_prop.return_value = 42
215
assert obj.computed == 42
216
mock_prop.__get__.assert_called_once()
217
```
218
219
### Mock Sealing
220
221
Prevent accidental attribute access on mocks.
222
223
```python { .api }
224
def seal(mock) -> None:
225
"""
226
Seal a mock to prevent creation of new attributes.
227
228
Parameters:
229
- mock: Mock object to seal
230
231
After sealing, accessing non-existent attributes raises AttributeError.
232
"""
233
```
234
235
Usage examples:
236
237
```python
238
from mock import Mock, seal
239
240
# Basic sealing
241
def test_mock_sealing():
242
mock_obj = Mock()
243
mock_obj.existing_attr = "value"
244
245
# Seal the mock
246
seal(mock_obj)
247
248
# Existing attributes still work
249
assert mock_obj.existing_attr == "value"
250
251
# New attributes raise AttributeError
252
try:
253
_ = mock_obj.new_attr
254
assert False, "Should have raised AttributeError"
255
except AttributeError:
256
pass # Expected
257
258
# Sealing prevents typos in tests
259
def test_seal_prevents_typos():
260
mock_service = Mock()
261
mock_service.process_data = Mock(return_value="result")
262
263
seal(mock_service)
264
265
# This works
266
result = mock_service.process_data("input")
267
assert result == "result"
268
269
# This would catch typos at runtime
270
try:
271
mock_service.proces_data("input") # Typo in method name
272
assert False, "Should catch typo"
273
except AttributeError:
274
pass # Typo caught
275
276
# Sealing with autospec
277
def test_seal_with_autospec():
278
from mock import create_autospec
279
280
class Service:
281
def method_one(self): pass
282
def method_two(self): pass
283
284
mock_service = create_autospec(Service)
285
seal(mock_service)
286
287
# Spec methods work
288
mock_service.method_one.return_value = "one"
289
mock_service.method_two.return_value = "two"
290
291
# Non-spec methods raise AttributeError
292
try:
293
mock_service.method_three()
294
assert False, "Should not allow non-spec method"
295
except AttributeError:
296
pass
297
```
298
299
### Sentinel Objects
300
301
Create unique sentinel values for testing.
302
303
```python { .api }
304
# Sentinel factory
305
sentinel: object # Factory for creating unique sentinel objects
306
307
# Individual sentinel object
308
class _SentinelObject:
309
def __init__(self, name: str) -> None: ...
310
name: str
311
312
# Usage: sentinel.ATTRIBUTE_NAME creates unique sentinel
313
```
314
315
Usage examples:
316
317
```python
318
from mock import sentinel
319
320
# Create unique sentinels
321
MISSING = sentinel.MISSING
322
EMPTY = sentinel.EMPTY
323
DEFAULT_VALUE = sentinel.DEFAULT_VALUE
324
325
def process_value(value=MISSING):
326
if value is MISSING:
327
return "no value provided"
328
elif value is EMPTY:
329
return "empty value"
330
else:
331
return f"value: {value}"
332
333
# Test with sentinels
334
def test_with_sentinels():
335
assert process_value() == "no value provided"
336
assert process_value(EMPTY) == "empty value"
337
assert process_value("real") == "value: real"
338
339
# Sentinels are unique
340
assert MISSING is not EMPTY
341
assert MISSING is not DEFAULT_VALUE
342
assert EMPTY is not DEFAULT_VALUE
343
344
# But same name creates same sentinel
345
assert sentinel.MISSING is MISSING
346
```
347
348
### Special Matching Objects
349
350
```python { .api }
351
# Match any value in assertions
352
ANY: object # Always equals any other object
353
354
# Default value marker
355
DEFAULT: object # Marker for default behavior in mocks
356
```
357
358
Usage examples:
359
360
```python
361
from mock import Mock, ANY, DEFAULT, call
362
363
# ANY matches anything
364
def test_any_matching():
365
mock_func = Mock()
366
mock_func("arg1", "arg2")
367
368
# These all pass
369
mock_func.assert_called_with("arg1", ANY)
370
mock_func.assert_called_with(ANY, "arg2")
371
mock_func.assert_called_with(ANY, ANY)
372
373
# ANY in call lists
374
def test_any_in_calls():
375
mock_func = Mock()
376
mock_func("first", 1)
377
mock_func("second", 2)
378
379
expected_calls = [
380
call("first", ANY),
381
call(ANY, 2)
382
]
383
mock_func.assert_has_calls(expected_calls)
384
385
# DEFAULT in side effects
386
def test_default_marker():
387
mock_func = Mock()
388
mock_func.side_effect = ["first", DEFAULT, "third"]
389
mock_func.return_value = "default_return"
390
391
assert mock_func() == "first"
392
assert mock_func() == "default_return" # DEFAULT uses return_value
393
assert mock_func() == "third"
394
```
395
396
## Type Definitions
397
398
```python { .api }
399
# Utility type definitions
400
class _SpecState:
401
"""Internal state for spec-based mocks."""
402
spec: Any
403
ids: Any
404
spec_set: Any
405
parent: Any
406
instance: Any
407
name: Any
408
409
class InvalidSpecError(Exception):
410
"""Raised when spec validation fails."""
411
```