0
# Utilities
1
2
The mock library provides several utility functions for creating specialized mocks and managing mock behavior in advanced testing scenarios.
3
4
## Capabilities
5
6
### create_autospec
7
8
Automatically create a mock with the same specification as another object, preserving function signatures and type information.
9
10
```python { .api }
11
def create_autospec(
12
spec,
13
spec_set=False,
14
instance=False,
15
_parent=None,
16
_name=None,
17
*,
18
unsafe=False,
19
**kwargs
20
):
21
"""
22
Create a mock object with automatic specification from another object.
23
24
Parameters:
25
- spec: Object to create specification from
26
- spec_set: If True, only attributes on spec can be set
27
- instance: If True, mock represents instance of spec rather than spec itself
28
- unsafe: Allow access to dangerous attributes
29
- **kwargs: Additional arguments passed to mock constructor
30
31
Returns:
32
Mock object with same interface as spec
33
34
The returned mock has the same signature as the original and will raise
35
TypeError if called with wrong arguments. Attributes and methods are
36
recursively auto-specced.
37
"""
38
```
39
40
### mock_open
41
42
Create a mock for the built-in open() function, useful for testing file operations without actual file I/O.
43
44
```python { .api }
45
def mock_open(mock=None, read_data=''):
46
"""
47
Create a mock for the built-in open() function.
48
49
Parameters:
50
- mock: Mock to configure (defaults to MagicMock)
51
- read_data: String data to return when file is read
52
53
Returns:
54
Mock object that behaves like built-in open()
55
56
The mock supports context manager protocol and file-like operations.
57
read(), readline(), and readlines() return data from read_data.
58
"""
59
```
60
61
### seal
62
63
Seal a mock to prevent creation of new attributes, useful for catching typos and ensuring test isolation.
64
65
```python { .api }
66
def seal(mock):
67
"""
68
Seal a mock to prevent creation of new attributes.
69
70
Parameters:
71
- mock: Mock object to seal
72
73
After sealing, accessing any new attributes will raise AttributeError.
74
Existing attributes and their children are also sealed recursively.
75
"""
76
```
77
78
## Usage Patterns
79
80
### Using create_autospec
81
82
```python
83
from mock import create_autospec
84
85
class RealClass:
86
def method(self, arg1, arg2, kwarg=None):
87
return 'real result'
88
89
@property
90
def prop(self):
91
return 'real property'
92
93
# Create autospec mock
94
mock_obj = create_autospec(RealClass)
95
96
# Mock has same signature - this works
97
mock_obj.method('a', 'b', kwarg='c')
98
99
# This raises TypeError - wrong signature
100
try:
101
mock_obj.method('too', 'many', 'args', 'here')
102
except TypeError:
103
print("Caught signature mismatch")
104
105
# Configure return values
106
mock_obj.method.return_value = 'mocked result'
107
result = mock_obj.method('a', 'b')
108
assert result == 'mocked result'
109
110
# Properties work too
111
mock_obj.prop = 'mocked property'
112
assert mock_obj.prop == 'mocked property'
113
```
114
115
### Instance vs Class Autospec
116
117
```python
118
from mock import create_autospec
119
120
class MyClass:
121
def __init__(self, value):
122
self.value = value
123
124
def method(self):
125
return self.value
126
127
# Mock the class itself
128
MockClass = create_autospec(MyClass)
129
instance = MockClass('test') # Returns mock instance
130
instance.method.return_value = 'mocked'
131
132
# Mock an instance of the class
133
mock_instance = create_autospec(MyClass, instance=True)
134
mock_instance.method.return_value = 'mocked'
135
# mock_instance('arg') # Would raise TypeError - instances aren't callable
136
```
137
138
### Using mock_open
139
140
```python
141
from mock import mock_open, patch
142
143
# Basic file reading
144
m = mock_open(read_data='file contents')
145
with patch('builtins.open', m):
146
with open('filename', 'r') as f:
147
data = f.read()
148
assert data == 'file contents'
149
150
# Mock file operations
151
m = mock_open()
152
with patch('builtins.open', m):
153
with open('filename', 'w') as f:
154
f.write('test data')
155
156
# Verify file was opened and written to
157
m.assert_called_once_with('filename', 'w')
158
handle = m()
159
handle.write.assert_called_once_with('test data')
160
161
# Multiple reads
162
m = mock_open(read_data='line1\nline2\nline3')
163
with patch('builtins.open', m):
164
with open('filename', 'r') as f:
165
lines = f.readlines()
166
assert lines == ['line1\n', 'line2\n', 'line3']
167
```
168
169
### File-like Object Operations
170
171
```python
172
from mock import mock_open, patch
173
174
# Test reading line by line
175
m = mock_open(read_data='line1\nline2\nline3')
176
with patch('builtins.open', m):
177
with open('filename', 'r') as f:
178
first_line = f.readline()
179
remaining = f.read()
180
181
assert first_line == 'line1\n'
182
assert remaining == 'line2\nline3'
183
184
# Test iteration
185
m = mock_open(read_data='line1\nline2\nline3')
186
with patch('builtins.open', m):
187
with open('filename', 'r') as f:
188
lines = list(f)
189
190
assert lines == ['line1\n', 'line2\n', 'line3']
191
```
192
193
### Using seal
194
195
```python
196
from mock import Mock, seal
197
198
# Create and configure mock
199
mock_obj = Mock()
200
mock_obj.existing_attr = 'value'
201
mock_obj.method.return_value = 'result'
202
203
# Seal the mock
204
seal(mock_obj)
205
206
# Existing attributes still work
207
assert mock_obj.existing_attr == 'value'
208
assert mock_obj.method() == 'result'
209
210
# New attributes raise AttributeError
211
try:
212
_ = mock_obj.new_attr # This will raise AttributeError
213
except AttributeError:
214
print("Caught access to new attribute")
215
216
try:
217
mock_obj.new_attr = 'value' # This will also raise AttributeError
218
except AttributeError:
219
print("Caught setting new attribute")
220
```
221
222
### Comprehensive File Testing
223
224
```python
225
from mock import mock_open, patch, call
226
227
def read_and_process_file(filename):
228
"""Function that reads a file and processes its contents."""
229
with open(filename, 'r') as f:
230
data = f.read()
231
232
# Process data somehow
233
processed = data.upper()
234
235
# Write result back
236
with open(filename + '.processed', 'w') as f:
237
f.write(processed)
238
239
return processed
240
241
# Test the function
242
m = mock_open(read_data='hello world')
243
with patch('builtins.open', m):
244
result = read_and_process_file('test.txt')
245
246
# Verify result
247
assert result == 'HELLO WORLD'
248
249
# Verify file operations
250
expected_calls = [
251
call('test.txt', 'r'),
252
call().__enter__(),
253
call().read(),
254
call().__exit__(None, None, None),
255
call('test.txt.processed', 'w'),
256
call().__enter__(),
257
call().write('HELLO WORLD'),
258
call().__exit__(None, None, None)
259
]
260
m.assert_has_calls(expected_calls)
261
```
262
263
### Autospec with Wrapping
264
265
```python
266
from mock import create_autospec
267
268
class Calculator:
269
def add(self, a, b):
270
return a + b
271
272
def multiply(self, a, b):
273
return a * b
274
275
real_calc = Calculator()
276
277
# Create autospec that wraps real object
278
mock_calc = create_autospec(Calculator, wrap=real_calc)
279
280
# Calls pass through to real object
281
result = mock_calc.add(2, 3)
282
assert result == 5 # Real calculation happened
283
284
# But we can still verify calls were made
285
mock_calc.add.assert_called_with(2, 3)
286
287
# And override specific methods when needed
288
mock_calc.multiply.return_value = 999
289
result = mock_calc.multiply(2, 3)
290
assert result == 999 # Mocked value, not real calculation
291
```