@@ -48,359 +48,22 @@ comparing calls.
48
48
.. |pre-commit | image :: https://results.pre-commit.ci/badge/github/pytest-dev/pytest-mock/master.svg
49
49
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest-mock/master
50
50
51
- `Professionally supported pytest-mock is now available <https://tidelift.com/subscription/pkg/pypi-pytest_mock?utm_source=pypi-pytest-mock&utm_medium=referral&utm_campaign=readme >`_
51
+ .. image :: https://readthedocs.org/projects/pytest-mock/badge/?version=latest
52
+ :target: https://pytest-mock.readthedocs.io/en/latest/?badge=latest
52
53
53
- Usage
54
- =====
55
54
56
- The ``mocker `` fixture has the same API as
57
- `mock.patch <https://docs.python.org/3/library/unittest.mock.html#patch >`_,
58
- supporting the same arguments:
55
+ `Professionally supported pytest-mock is available <https://tidelift.com/subscription/pkg/pypi-pytest_mock?utm_source=pypi-pytest-mock&utm_medium=referral&utm_campaign=readme >`_.
59
56
60
- .. code-block :: python
61
-
62
- def test_foo (mocker ):
63
- # all valid calls
64
- mocker.patch(' os.remove' )
65
- mocker.patch.object(os, ' listdir' , autospec = True )
66
- mocked_isfile = mocker.patch(' os.path.isfile' )
67
-
68
- The supported methods are:
69
-
70
- * `mocker.patch <https://docs.python.org/3/library/unittest.mock.html#patch >`_
71
- * `mocker.patch.object <https://docs.python.org/3/library/unittest.mock.html#patch-object >`_
72
- * `mocker.patch.multiple <https://docs.python.org/3/library/unittest.mock.html#patch-multiple >`_
73
- * `mocker.patch.dict <https://docs.python.org/3/library/unittest.mock.html#patch-dict >`_
74
- * `mocker.stopall <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch.stopall >`_
75
- * ``mocker.resetall() ``: calls `reset_mock() <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.reset_mock >`_ in all mocked objects up to this point.
76
-
77
- Also, as a convenience, these names from the ``mock `` module are accessible directly from ``mocker ``:
78
-
79
- * `Mock <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock >`_
80
- * `MagicMock <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.MagicMock >`_
81
- * `PropertyMock <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.PropertyMock >`_
82
- * `ANY <https://docs.python.org/3/library/unittest.mock.html#any >`_
83
- * `DEFAULT <https://docs.python.org/3/library/unittest.mock.html#default >`_ *(Version 1.4) *
84
- * `call <https://docs.python.org/3/library/unittest.mock.html#call >`_ *(Version 1.1) *
85
- * `sentinel <https://docs.python.org/3/library/unittest.mock.html#sentinel >`_ *(Version 1.2) *
86
- * `mock_open <https://docs.python.org/3/library/unittest.mock.html#mock-open >`_
87
- * `seal <https://docs.python.org/3/library/unittest.mock.html#unittest.mock.seal >`_ *(Version 3.4) *
88
-
89
- It is also possible to use mocking functionality from fixtures of other scopes using
90
- the appropriate mock fixture:
91
-
92
- * ``class_mocker ``
93
- * ``module_mocker ``
94
- * ``package_mocker ``
95
- * ``session_mocker ``
96
-
97
- Type Annotations
98
- ----------------
99
-
100
- *New in version 3.3.0. *
101
-
102
- ``pytest-mock `` is fully type annotated, letting users use static type checkers to
103
- test their code.
104
-
105
- The ``mocker `` fixture returns ``pytest_mock.MockerFixture `` which can be used
106
- to annotate test functions:
107
-
108
- .. code-block :: python
109
-
110
- from pytest_mock import MockerFixture
111
-
112
- def test_foo (mocker : MockerFixture) -> None :
113
- ...
114
-
115
- The type annotations have been checked with ``mypy ``, which is the only
116
- type checker supported at the moment; other type-checkers might work
117
- but are not currently tested.
118
-
119
- Spy
120
- ---
121
-
122
- The ``mocker.spy `` object acts exactly like the original method in all cases, except the spy
123
- also tracks function/method calls, return values and exceptions raised.
124
-
125
- .. code-block :: python
126
-
127
- def test_spy_method (mocker ):
128
- class Foo (object ):
129
- def bar (self , v ):
130
- return v * 2
131
-
132
- foo = Foo()
133
- spy = mocker.spy(foo, ' bar' )
134
- assert foo.bar(21 ) == 42
135
-
136
- spy.assert_called_once_with(21 )
137
- assert spy.spy_return == 42
138
-
139
- def test_spy_function (mocker ):
140
- # mymodule declares `myfunction` which just returns 42
141
- import mymodule
142
-
143
- spy = mocker.spy(mymodule, " myfunction" )
144
- assert mymodule.myfunction() == 42
145
- assert spy.call_count == 1
146
- assert spy.spy_return == 42
147
-
148
- The object returned by ``mocker.spy `` is a ``MagicMock `` object, so all standard checking functions
149
- are available (like ``assert_called_once_with `` or ``call_count `` in the examples above).
150
-
151
- In addition, spy objects contain two extra attributes:
152
-
153
- * ``spy_return ``: contains the returned value of the spied function.
154
- * ``spy_exception ``: contain the last exception value raised by the spied function/method when
155
- it was last called, or ``None `` if no exception was raised.
156
-
157
- Besides functions and normal methods, ``mocker.spy `` also works for class and static methods.
158
-
159
- As of version 3.0.0, ``mocker.spy `` also works with ``async def `` functions.
160
-
161
- .. note ::
162
-
163
- In versions earlier than ``2.0 ``, the attributes were called ``return_value `` and
164
- ``side_effect `` respectively, but due to incompatibilities with ``unittest.mock ``
165
- they had to be renamed (see `#175 `_ for details).
166
-
167
- .. _#175 : https://github.com/pytest-dev/pytest-mock/issues/175
168
-
169
- Stub
170
- ----
171
-
172
- The stub is a mock object that accepts any arguments and is useful to test callbacks.
173
- It may receive an optional name that is shown in its ``repr ``, useful for debugging.
174
-
175
- .. code-block :: python
176
-
177
- def test_stub (mocker ):
178
- def foo (on_something ):
179
- on_something(' foo' , ' bar' )
180
-
181
- stub = mocker.stub(name = ' on_something_stub' )
182
-
183
- foo(stub)
184
- stub.assert_called_once_with(' foo' , ' bar' )
185
-
186
-
187
- Improved reporting of mock call assertion errors
188
- ------------------------------------------------
189
-
190
- This plugin monkeypatches the mock library to improve pytest output for failures
191
- of mock call assertions like ``Mock.assert_called_with() `` by hiding internal traceback
192
- entries from the ``mock `` module.
193
-
194
- It also adds introspection information on differing call arguments when
195
- calling the helper methods. This features catches `AssertionError ` raised in
196
- the method, and uses pytest's own `advanced assertions `_ to return a better
197
- diff::
198
-
199
-
200
- mocker = <pytest_mock.MockerFixture object at 0x0381E2D0>
201
-
202
- def test(mocker):
203
- m = mocker.Mock()
204
- m('fo')
205
- > m.assert_called_once_with('', bar=4)
206
- E AssertionError: Expected call: mock('', bar=4)
207
- E Actual call: mock('fo')
208
- E
209
- E pytest introspection follows:
210
- E
211
- E Args:
212
- E assert ('fo',) == ('',)
213
- E At index 0 diff: 'fo' != ''
214
- E Use -v to get the full diff
215
- E Kwargs:
216
- E assert {} == {'bar': 4}
217
- E Right contains more items:
218
- E {'bar': 4}
219
- E Use -v to get the full diff
220
-
221
-
222
- test_foo.py:6: AssertionError
223
- ========================== 1 failed in 0.03 seconds ===========================
224
-
225
-
226
- This is useful when asserting mock calls with many/nested arguments and trying
227
- to quickly see the difference.
228
-
229
- This feature is probably safe, but if you encounter any problems it can be disabled in
230
- your ``pytest.ini `` file:
231
-
232
- .. code-block :: ini
233
-
234
- [pytest]
235
- mock_traceback_monkeypatch = false
236
-
237
- Note that this feature is automatically disabled with the ``--tb=native `` option. The underlying
238
- mechanism used to suppress traceback entries from ``mock `` module does not work with that option
239
- anyway plus it generates confusing messages on Python 3.5 due to exception chaining
240
-
241
- .. _advanced assertions : http://docs.pytest.org/en/stable/assert.html
242
57
58
+ Documentation
59
+ =============
243
60
244
- Use standalone "mock" package
245
- -----------------------------
246
-
247
- *New in version 1.4.0. *
248
-
249
- Python 3 users might want to use a newest version of the ``mock `` package as published on PyPI
250
- than the one that comes with the Python distribution.
251
-
252
- .. code-block :: ini
253
-
254
- [pytest]
255
- mock_use_standalone_module = true
256
-
257
- This will force the plugin to import ``mock `` instead of the ``unittest.mock `` module bundled with
258
- Python 3.4+. Note that this option is only used in Python 3+, as Python 2 users only have the option
259
- to use the ``mock `` package from PyPI anyway.
260
-
261
- Note about usage as context manager
262
- -----------------------------------
263
-
264
- Although mocker's API is intentionally the same as ``mock.patch ``'s, its use
265
- as context manager and function decorator is **not ** supported through the
266
- fixture:
267
-
268
- .. code-block :: python
269
-
270
- def test_context_manager (mocker ):
271
- a = A()
272
- with mocker.patch.object(a, ' doIt' , return_value = True , autospec = True ): # DO NOT DO THIS
273
- assert a.doIt() == True
274
-
275
- The purpose of this plugin is to make the use of context managers and
276
- function decorators for mocking unnecessary, so it will emit a warning when used as such.
277
-
278
- If you really intend to mock a context manager, ``mocker.patch.context_manager `` exists
279
- which won't issue the above warning.
280
-
281
-
282
- Install
283
- =======
284
-
285
- Install using `pip <http://pip-installer.org/ >`_:
286
-
287
- .. code-block :: console
288
-
289
- $ pip install pytest-mock
290
-
291
- Changelog
292
- =========
293
-
294
- Please consult the `changelog page `_.
295
-
296
- .. _changelog page : https://github.com/pytest-dev/pytest-mock/blob/master/CHANGELOG.rst
297
-
298
- Why bother with a plugin?
299
- =========================
300
-
301
- There are a number of different ``patch `` usages in the standard ``mock `` API,
302
- but IMHO they don't scale very well when you have more than one or two
303
- patches to apply.
304
-
305
- It may lead to an excessive nesting of ``with `` statements, breaking the flow
306
- of the test:
307
-
308
- .. code-block :: python
309
-
310
- import mock
311
-
312
- def test_unix_fs ():
313
- with mock.patch(' os.remove' ):
314
- UnixFS.rm(' file' )
315
- os.remove.assert_called_once_with(' file' )
316
-
317
- with mock.patch(' os.listdir' ):
318
- assert UnixFS.ls(' dir' ) == expected
319
- # ...
320
-
321
- with mock.patch(' shutil.copy' ):
322
- UnixFS.cp(' src' , ' dst' )
323
- # ...
324
-
325
-
326
- One can use ``patch `` as a decorator to improve the flow of the test:
327
-
328
- .. code-block :: python
329
-
330
- @mock.patch (' os.remove' )
331
- @mock.patch (' os.listdir' )
332
- @mock.patch (' shutil.copy' )
333
- def test_unix_fs (mocked_copy , mocked_listdir , mocked_remove ):
334
- UnixFS.rm(' file' )
335
- os.remove.assert_called_once_with(' file' )
336
-
337
- assert UnixFS.ls(' dir' ) == expected
338
- # ...
339
-
340
- UnixFS.cp(' src' , ' dst' )
341
- # ...
342
-
343
- But this poses a few disadvantages:
344
-
345
- - test functions must receive the mock objects as parameter, even if you don't plan to
346
- access them directly; also, order depends on the order of the decorated ``patch ``
347
- functions;
348
- - receiving the mocks as parameters doesn't mix nicely with pytest's approach of
349
- naming fixtures as parameters, or ``pytest.mark.parametrize ``;
350
- - you can't easily undo the mocking during the test execution;
351
-
352
- An alternative is to use ``contextlib.ExitStack `` to stack the context managers in a single level of indentation
353
- to improve the flow of the test:
354
-
355
- .. code-block :: python
356
-
357
- import contextlib
358
- import mock
359
-
360
- def test_unix_fs ():
361
- with contextlib.ExitStack() as stack:
362
- stack.enter_context(mock.patch(' os.remove' ))
363
- UnixFS.rm(' file' )
364
- os.remove.assert_called_once_with(' file' )
365
-
366
- stack.enter_context(mock.patch(' os.listdir' ))
367
- assert UnixFS.ls(' dir' ) == expected
368
- # ...
369
-
370
- stack.enter_context(mock.patch(' shutil.copy' ))
371
- UnixFS.cp(' src' , ' dst' )
372
- # ...
373
-
374
- But this is arguably a little more complex than using ``pytest-mock ``.
375
-
376
- Contributing
377
- ============
378
-
379
- Contributions are welcome! After cloning the repository, create a virtual env
380
- and install ``pytest-mock `` in editable mode with ``dev `` extras:
381
-
382
- .. code-block :: console
383
-
384
- $ pip install --editable .[dev]
385
- $ pre-commit install
386
-
387
- Tests are run with ``tox ``, you can run the baseline environments before submitting a PR:
388
-
389
- .. code-block :: console
390
-
391
- $ tox -e py38,linting
392
-
393
- Style checks and formatting are done automatically during commit courtesy of
394
- `pre-commit <https://pre-commit.com >`_.
61
+ For full documentation, please see https://pytest-mock.readthedocs.io/en/latest.
395
62
396
63
License
397
64
=======
398
65
399
66
Distributed under the terms of the `MIT `_ license.
400
67
401
- Security contact information
402
- ============================
403
-
404
- To report a security vulnerability, please use the `Tidelift security contact <https://tidelift.com/security >`__. Tidelift will coordinate the fix and disclosure.
405
68
406
69
.. _MIT : https://github.com/pytest-dev/pytest-mock/blob/master/LICENSE
0 commit comments