├── .carthorse.yml ├── .circleci └── config.yml ├── .coveragerc ├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── .readthedocs.yml ├── CHANGELOG.rst ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── backport.py ├── docs ├── changelog.txt ├── conf.py └── index.txt ├── lastsync.txt ├── mock ├── __init__.py ├── backports.py ├── mock.py └── tests │ ├── __init__.py │ ├── support.py │ ├── testasync.py │ ├── testcallable.py │ ├── testhelpers.py │ ├── testmagicmethods.py │ ├── testmock.py │ ├── testpatch.py │ ├── testsealable.py │ ├── testsentinel.py │ ├── testthreadingmock.py │ └── testwith.py ├── release.py ├── setup.cfg └── setup.py /.carthorse.yml: -------------------------------------------------------------------------------- 1 | carthorse: 2 | version-from: setup.py 3 | tag-format: "{version}" 4 | when: 5 | - version-not-tagged 6 | actions: 7 | - run: "pip install -e .[build]" 8 | - run: "twine upload -u __token__ -p $PYPI_TOKEN dist/*" 9 | - create-tag 10 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | orbs: 4 | python: cjw296/python-ci@5 5 | 6 | jobs: 7 | check-package: 8 | parameters: 9 | image: 10 | type: string 11 | python: 12 | type: string 13 | default: "python" 14 | docker: 15 | - image: << parameters.image >> 16 | steps: 17 | - python/check-package: 18 | package: "mock" 19 | test: 20 | - run: 21 | name: "Import package" 22 | command: << parameters.python >> -c "import mock" 23 | 24 | 25 | common: &common 26 | jobs: 27 | 28 | - python/pip-run-tests: 29 | matrix: 30 | alias: python-tests 31 | parameters: 32 | image: 33 | - cimg/python:3.6 34 | - cimg/python:3.7 35 | - cimg/python:3.8 36 | - cimg/python:3.9 37 | - cimg/python:3.10 38 | - cimg/python:3.11 39 | - cimg/python:3.12 40 | - cimg/python:3.13 41 | 42 | - python/pip-run-tests: 43 | python: pypy3 44 | matrix: 45 | alias: pypy-tests 46 | parameters: 47 | image: 48 | - pypy:3.7-7.3.2 49 | - pypy:latest 50 | 51 | - python/coverage: 52 | name: coverage 53 | requires: 54 | - python-tests 55 | - pypy-tests 56 | 57 | - python/pip-docs: 58 | name: docs 59 | requires: 60 | - coverage 61 | 62 | - python/pip-setuptools-build-package: 63 | name: package 64 | requires: 65 | - docs 66 | filters: 67 | branches: 68 | only: master 69 | 70 | - check-package: 71 | matrix: 72 | parameters: 73 | image: 74 | - cimg/python:3.6 75 | - cimg/python:3.13 76 | requires: 77 | - package 78 | 79 | - python/release: 80 | name: release 81 | config: .carthorse.yml 82 | requires: 83 | - check-package 84 | 85 | workflows: 86 | push: 87 | <<: *common 88 | periodic: 89 | <<: *common 90 | triggers: 91 | - schedule: 92 | cron: "0 1 * * *" 93 | filters: 94 | branches: 95 | only: master 96 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = mock 3 | 4 | [report] 5 | exclude_lines = 6 | pragma: no cover 7 | if __name__ == .__main__.: 8 | : pass 9 | : yield 10 | 11 | [paths] 12 | source = 13 | mock/ 14 | /root/project/mock/ 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Only report bugs here that are specific to this backport. 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | This package is a rolling backport of [`unittest.mock`](https://github.com/python/cpython/blob/master/Lib/unittest/mock.py). 11 | As such, any problems you encounter most likely need to be fixed upstream. 12 | 13 | Before submitting an issue here, please try and reproduce the problem on the latest release of Python 3, including alphas, and replace any import from `mock` with ones from `unittest.mock`. 14 | 15 | If the issue still occurs, then please report upstream through https://github.com/python/cpython/issues as it will need to be fixed there so that it can be backported here and released to you. 16 | 17 | If the issue does not occur upstream, please file an issue using the template below as it may be an issue specific to the backport: 18 | 19 | **What versions are you using?** 20 | - Python: [e.g. 3.7.1] 21 | - Mock: [e.g. 4.0.2] 22 | - Operating System: [e.g.Linux, macOS, Windows] 23 | 24 | **What happened?** 25 | 26 | 29 | 30 | **What were you hoping to happen instead?** 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*\.pyc 2 | html/ 3 | mock\.egg-info/ 4 | mock\.wpu 5 | \.tox/ 6 | build 7 | dist 8 | latex 9 | .*\$py\.class 10 | runtox 11 | *~ 12 | *.pyc 13 | .testrepository 14 | .*.swp 15 | README.html 16 | .coverage 17 | .coverage.* 18 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: ubuntu-22.04 5 | tools: 6 | python: "3" 7 | 8 | python: 9 | install: 10 | - method: pip 11 | path: . 12 | extra_requirements: 13 | - docs 14 | sphinx: 15 | fail_on_warning: true 16 | configuration: docs/conf.py 17 | -------------------------------------------------------------------------------- /CHANGELOG.rst: -------------------------------------------------------------------------------- 1 | 5.2.0 2 | ----- 3 | 4 | This is release is `in memory of Michael Foord`__, who originally authored the `mock` package 5 | and passed away in January 2025. 6 | 7 | __ https://discuss.python.org/t/in-memoriam-michael-foord-1974-2025/78317 8 | 9 | - gh-65454: :func:`unittest.mock.Mock.attach_mock` no longer triggers a call 10 | to a ``PropertyMock`` being attached. 11 | 12 | - gh-117765: Improved documentation for :func:`unittest.mock.patch.dict` 13 | 14 | - gh-124176: Add support for :func:`dataclasses.dataclass` in 15 | :func:`unittest.mock.create_autospec`. Now ``create_autospec`` will check 16 | for potential dataclasses and use :func:`dataclasses.fields` function to 17 | retrieve the spec information. 18 | 19 | - gh-123934: Fix :class:`unittest.mock.MagicMock` reseting magic methods 20 | return values after ``.reset_mock(return_value=True)`` was called. 21 | 22 | - gh-90848: Fixed :func:`unittest.mock.create_autospec` to configure parent 23 | mock with keyword arguments. 24 | 25 | - gh-113569: Indicate if there were no actual calls in unittest 26 | :meth:`~unittest.mock.Mock.assert_has_calls` failure. 27 | 28 | - gh-122858: Deprecate :func:`!asyncio.iscoroutinefunction` in favor of 29 | :func:`inspect.iscoroutinefunction`. 30 | 31 | - gh-104745: Limit starting a patcher (from :func:`unittest.mock.patch` or 32 | :func:`unittest.mock.patch.object`) more than once without stopping it 33 | 34 | - gh-75988: Fixed :func:`unittest.mock.create_autospec` to pass the call 35 | through to the wrapped object to return the real result. 36 | 37 | - gh-119600: Fix :func:`unittest.mock.patch` to not read attributes of the 38 | target when ``new_callable`` is set. Patch by Robert Collins. 39 | 40 | - gh-113407: Fix import of :mod:`unittest.mock` when CPython is built 41 | without docstrings. 42 | 43 | - gh-120732: Fix ``name`` passing to :class:`unittest.mock.Mock` object when 44 | using :func:`unittest.mock.create_autospec`. 45 | 46 | 5.1.0 47 | ----- 48 | 49 | - bpo-44185: :func:`unittest.mock.mock_open` will call the :func:`close` 50 | method of the file handle mock when it is exiting from the context 51 | manager. Patch by Samet Yaslan. 52 | 53 | - gh-94924: :func:`unittest.mock.create_autospec` now properly returns 54 | coroutine functions compatible with :func:`inspect.iscoroutinefunction` 55 | 56 | - bpo-17013: Add ``ThreadingMock`` to :mod:`unittest.mock` that can be used 57 | to create Mock objects that can wait until they are called. Patch by 58 | Karthikeyan Singaravelan and Mario Corchero. 59 | 60 | - bpo-41768: :mod:`unittest.mock` speccing no longer calls class properties. 61 | Patch by Melanie Witt. 62 | 63 | 5.0.2 64 | ----- 65 | 66 | - gh-102978: Fixes :func:`unittest.mock.patch` not enforcing function 67 | signatures for methods decorated with ``@classmethod`` or 68 | ``@staticmethod`` when patch is called with ``autospec=True``. 69 | 70 | - gh-103329: Regression tests for the behaviour of 71 | ``unittest.mock.PropertyMock`` were added. 72 | 73 | 5.0.1 74 | ----- 75 | 76 | - gh-100740: Fix ``unittest.mock.Mock`` not respecting the spec for 77 | attribute names prefixed with ``assert``. 78 | 79 | - gh-100690: ``Mock`` objects which are not unsafe will now raise an 80 | ``AttributeError`` when accessing an attribute that matches the name of an 81 | assertion but without the prefix ``assert_``, e.g. accessing 82 | ``called_once`` instead of ``assert_called_once``. This is in addition to 83 | this already happening for accessing attributes with prefixes ``assert``, 84 | ``assret``, ``asert``, ``aseert``, and ``assrt``. 85 | 86 | - gh-96127: ``inspect.signature`` was raising ``TypeError`` on call with 87 | mock objects. Now it correctly returns ``(*args, **kwargs)`` as infered 88 | signature. 89 | 90 | 5.0.0 91 | ----- 92 | 93 | - gh-98624: Add a mutex to unittest.mock.NonCallableMock to protect 94 | concurrent access to mock attributes. 95 | 96 | - bpo-43478: Mocks can no longer be used as the specs for other Mocks. As a 97 | result, an already-mocked object cannot have an attribute mocked using 98 | `autospec=True` or be the subject of a `create_autospec(...)` call. This 99 | can uncover bugs in tests since these Mock-derived Mocks will always pass 100 | certain tests (e.g. isinstance) and builtin assert functions (e.g. 101 | assert_called_once_with) will unconditionally pass. 102 | 103 | - bpo-45156: Fixes infinite loop on :func:`unittest.mock.seal` of mocks 104 | created by :func:`~unittest.create_autospec`. 105 | 106 | - bpo-41403: Make :meth:`mock.patch` raise a :exc:`TypeError` with a 107 | relevant error message on invalid arg. Previously it allowed a cryptic 108 | :exc:`AttributeError` to escape. 109 | 110 | - gh-91803: Fix an error when using a method of objects mocked with 111 | :func:`unittest.mock.create_autospec` after it was sealed with 112 | :func:`unittest.mock.seal` function. 113 | 114 | - bpo-41877: AttributeError for suspected misspellings of assertions on 115 | mocks are now pointing out that the cause are misspelled assertions and 116 | also what to do if the misspelling is actually an intended attribute name. 117 | The unittest.mock document is also updated to reflect the current set of 118 | recognised misspellings. 119 | 120 | - bpo-43478: Mocks can no longer be provided as the specs for other Mocks. 121 | As a result, an already-mocked object cannot be passed to `mock.Mock()`. 122 | This can uncover bugs in tests since these Mock-derived Mocks will always 123 | pass certain tests (e.g. isinstance) and builtin assert functions (e.g. 124 | assert_called_once_with) will unconditionally pass. 125 | 126 | - bpo-45010: Remove support of special method ``__div__`` in 127 | :mod:`unittest.mock`. It is not used in Python 3. 128 | 129 | - gh-84753: :func:`inspect.iscoroutinefunction` now properly returns 130 | ``True`` when an instance of :class:`unittest.mock.AsyncMock` is passed to 131 | it. This makes it consistent with behavior of 132 | :func:`asyncio.iscoroutinefunction`. Patch by Mehdi ABAAKOUK. 133 | 134 | - bpo-46852: Remove the undocumented private ``float.__set_format__()`` 135 | method, previously known as ``float.__setformat__()`` in Python 3.7. Its 136 | docstring said: "You probably don't want to use this function. It exists 137 | mainly to be used in Python's test suite." Patch by Victor Stinner. 138 | 139 | - gh-98086: Make sure ``patch.dict()`` can be applied on async functions. 140 | 141 | - gh-100287: Fix the interaction of :func:`unittest.mock.seal` with 142 | :class:`unittest.mock.AsyncMock`. 143 | 144 | - gh-83076: Instantiation of ``Mock()`` and ``AsyncMock()`` is now 3.8x 145 | faster. 146 | 147 | - bpo-41877: A check is added against misspellings of autospect, auto_spec 148 | and set_spec being passed as arguments to patch, patch.object and 149 | create_autospec. 150 | 151 | 4.0.3 152 | ----- 153 | 154 | - bpo-42532: Remove unexpected call of ``__bool__`` when passing a 155 | ``spec_arg`` argument to a Mock. 156 | 157 | - bpo-39966: Revert bpo-25597. :class:`unittest.mock.MagicMock` with 158 | wraps' set uses default return values for magic methods. 159 | 160 | - bpo-41877: Mock objects which are not unsafe will now raise an 161 | AttributeError if an attribute with the prefix asert, aseert, or assrt is 162 | accessed, in addition to this already happening for the prefixes assert or 163 | assret. 164 | 165 | - bpo-40126: Fixed reverting multiple patches in unittest.mock. Patcher's 166 | ``__exit__()`` is now never called if its ``__enter__()`` is failed. 167 | Returning true from ``__exit__()`` silences now the exception. 168 | 169 | 4.0.2 170 | ----- 171 | 172 | - bpo-39915: Ensure :attr:`unittest.mock.AsyncMock.await_args_list` has 173 | call objects in the order of awaited arguments instead of using 174 | :attr:`unittest.mock.Mock.call_args` which has the last value of the call. 175 | Patch by Karthikeyan Singaravelan. 176 | 177 | 4.0.1 178 | ----- 179 | 180 | - Remove the universal marker from the wheel. 181 | 182 | 4.0.0 183 | ----- 184 | 185 | - No Changes from 4.0.0b1. 186 | 187 | 4.0.0b1 188 | ------- 189 | 190 | - The release is a fresh cut of cpython's `4a686504`__. All changes to :mod:`mock` 191 | from that commit and before are included in this release along with the 192 | subsequent changes listed below. 193 | 194 | __ https://github.com/python/cpython/commit/4a686504eb2bbf69adf78077458508a7ba131667 195 | 196 | - bpo-37972: Subscripts to the `unittest.mock.call` objects now receive 197 | the same chaining mechanism as any other custom attributes, so that the 198 | following usage no longer raises a `TypeError`: 199 | 200 | call().foo().__getitem__('bar') 201 | 202 | Patch by blhsing 203 | 204 | - bpo-38839: Fix some unused functions in tests. Patch by Adam Johnson. 205 | 206 | - bpo-39485: Fix a bug in :func:`unittest.mock.create_autospec` that 207 | would complain about the wrong number of arguments for custom descriptors 208 | defined in an extension module returning functions. 209 | 210 | - bpo-39082: Allow AsyncMock to correctly patch static/class methods 211 | 212 | - bpo-38093: Fixes AsyncMock so it doesn't crash when used with 213 | AsyncContextManagers or AsyncIterators. 214 | 215 | - bpo-38859: AsyncMock now returns StopAsyncIteration on the exaustion of 216 | a side_effects iterable. Since PEP-479 its Impossible to raise a 217 | StopIteration exception from a coroutine. 218 | 219 | - bpo-38163: Child mocks will now detect their type as either synchronous 220 | or asynchronous, asynchronous child mocks will be AsyncMocks and 221 | synchronous child mocks will be either MagicMock or Mock (depending on 222 | their parent type). 223 | 224 | - bpo-38473: Use signature from inner mock for autospecced methods 225 | attached with :func:`unittest.mock.attach_mock`. Patch by Karthikeyan 226 | Singaravelan. 227 | 228 | - bpo-38136: Changes AsyncMock call count and await count to be two 229 | different counters. Now await count only counts when a coroutine has been 230 | awaited, not when it has been called, and vice-versa. Update the 231 | documentation around this. 232 | 233 | - bpo-37555: Fix `NonCallableMock._call_matcher` returning tuple instead 234 | of `_Call` object when `self._spec_signature` exists. Patch by Elizabeth 235 | Uselton 236 | 237 | - bpo-37251: Remove `__code__` check in AsyncMock that incorrectly 238 | evaluated function specs as async objects but failed to evaluate classes 239 | with `__await__` but no `__code__` attribute defined as async objects. 240 | 241 | - bpo-38669: Raise :exc:`TypeError` when passing target as a string with 242 | :meth:`unittest.mock.patch.object`. 243 | 244 | - bpo-25597: Ensure, if ``wraps`` is supplied to 245 | :class:`unittest.mock.MagicMock`, it is used to calculate return values 246 | for the magic methods instead of using the default return values. Patch by 247 | Karthikeyan Singaravelan. 248 | 249 | - bpo-38108: Any synchronous magic methods on an AsyncMock now return a 250 | MagicMock. Any asynchronous magic methods on a MagicMock now return an 251 | AsyncMock. 252 | 253 | - bpo-21478: Record calls to parent when autospecced object is attached 254 | to a mock using :func:`unittest.mock.attach_mock`. Patch by Karthikeyan 255 | Singaravelan. 256 | 257 | - bpo-38857: AsyncMock fix for return values that are awaitable types. 258 | This also covers side_effect iterable values that happend to be awaitable, 259 | and wraps callables that return an awaitable type. Before these awaitables 260 | were being awaited instead of being returned as is. 261 | 262 | - bpo-38932: Mock fully resets child objects on reset_mock(). Patch by 263 | Vegard Stikbakke 264 | 265 | - bpo-37685: Fixed ``__eq__``, ``__lt__`` etc implementations in some 266 | classes. They now return :data:`NotImplemented` for unsupported type of 267 | the other operand. This allows the other operand to play role (for example 268 | the equality comparison with :data:`~unittest.mock.ANY` will return 269 | ``True``). 270 | 271 | - bpo-37212: :func:`unittest.mock.call` now preserves the order of 272 | keyword arguments in repr output. Patch by Karthikeyan Singaravelan. 273 | 274 | - bpo-37828: Fix default mock name in 275 | :meth:`unittest.mock.Mock.assert_called` exceptions. Patch by Abraham 276 | Toriz Cruz. 277 | 278 | - bpo-36871: Improve error handling for the assert_has_calls and 279 | assert_has_awaits methods of mocks. Fixed a bug where any errors 280 | encountered while binding the expected calls to the mock's spec were 281 | silently swallowed, leading to misleading error output. 282 | 283 | - bpo-21600: Fix :func:`mock.patch.stopall` to stop active patches that 284 | were created with :func:`mock.patch.dict`. 285 | 286 | - bpo-38161: Removes _AwaitEvent from AsyncMock. 287 | 288 | - bpo-36871: Ensure method signature is used instead of constructor 289 | signature of a class while asserting mock object against method calls. 290 | Patch by Karthikeyan Singaravelan. 291 | 292 | 3.0.5 293 | ----- 294 | 295 | - bpo-31855: :func:`unittest.mock.mock_open` results now respects the 296 | argument of read([size]). Patch contributed by Rémi Lapeyre. 297 | 298 | 3.0.4 299 | ----- 300 | 301 | - Include the license, readme and changelog in the source distribution. 302 | 303 | 3.0.3 304 | ----- 305 | 306 | - Fixed patching of dictionaries, when specifying the target with a 307 | unicode on Python 2. 308 | 309 | 3.0.2 310 | ----- 311 | 312 | - Add missing ``funcsigs`` dependency on Python 2. 313 | 314 | 3.0.1 315 | ----- 316 | 317 | - Fix packaging issue where ``six`` was missed as a dependency. 318 | 319 | 3.0.0 320 | ----- 321 | 322 | - bpo-35226: Recursively check arguments when testing for equality of 323 | :class:`unittest.mock.call` objects and add note that tracking of 324 | parameters used to create ancestors of mocks in ``mock_calls`` is not 325 | possible. 326 | 327 | - bpo-31177: Fix bug that prevented using :meth:`reset_mock 328 | ` on mock instances with deleted attributes 329 | 330 | - bpo-26704: Added test demonstrating double-patching of an instance 331 | method. Patch by Anthony Sottile. 332 | 333 | - bpo-35500: Write expected and actual call parameters on separate lines 334 | in :meth:`unittest.mock.Mock.assert_called_with` assertion errors. 335 | Contributed by Susan Su. 336 | 337 | - bpo-35330: When a :class:`Mock` instance was used to wrap an object, if 338 | `side_effect` is used in one of the mocks of it methods, don't call the 339 | original implementation and return the result of using the side effect the 340 | same way that it is done with return_value. 341 | 342 | - bpo-30541: Add new function to seal a mock and prevent the 343 | automatically creation of child mocks. Patch by Mario Corchero. 344 | 345 | - bpo-35022: :class:`unittest.mock.MagicMock` now supports the 346 | ``__fspath__`` method (from :class:`os.PathLike`). 347 | 348 | - bpo-33516: :class:`unittest.mock.MagicMock` now supports the 349 | ``__round__`` magic method. 350 | 351 | - bpo-35512: :func:`unittest.mock.patch.dict` used as a decorator with 352 | string target resolves the target during function call instead of during 353 | decorator construction. Patch by Karthikeyan Singaravelan. 354 | 355 | - bpo-36366: Calling ``stop()`` on an unstarted or stopped 356 | :func:`unittest.mock.patch` object will now return `None` instead of 357 | raising :exc:`RuntimeError`, making the method idempotent. Patch 358 | byKarthikeyan Singaravelan. 359 | 360 | - bpo-35357: Internal attributes' names of unittest.mock._Call and 361 | unittest.mock.MagicProxy (name, parent & from_kall) are now prefixed with 362 | _mock_ in order to prevent clashes with widely used object attributes. 363 | Fixed minor typo in test function name. 364 | 365 | - bpo-20239: Allow repeated assignment deletion of 366 | :class:`unittest.mock.Mock` attributes. Patch by Pablo Galindo. 367 | 368 | - bpo-35082: Don't return deleted attributes when calling dir on a 369 | :class:`unittest.mock.Mock`. 370 | 371 | - bpo-0: Improved an error message when mock assert_has_calls fails. 372 | 373 | - bpo-23078: Add support for :func:`classmethod` and :func:`staticmethod` 374 | to :func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa. 375 | 376 | - bpo-21478: Calls to a child function created with 377 | :func:`unittest.mock.create_autospec` should propagate to the parent. 378 | Patch by Karthikeyan Singaravelan. 379 | 380 | - bpo-36598: Fix ``isinstance`` check for Mock objects with spec when the 381 | code is executed under tracing. Patch by Karthikeyan Singaravelan. 382 | 383 | - bpo-32933: :func:`unittest.mock.mock_open` now supports iteration over 384 | the file contents. Patch by Tony Flury. 385 | 386 | - bpo-21269: Add ``args`` and ``kwargs`` properties to mock call objects. 387 | Contributed by Kumar Akshay. 388 | 389 | - bpo-17185: Set ``__signature__`` on mock for :mod:`inspect` to get 390 | signature. Patch by Karthikeyan Singaravelan. 391 | 392 | - bpo-35047: ``unittest.mock`` now includes mock calls in exception 393 | messages if ``assert_not_called``, ``assert_called_once``, or 394 | ``assert_called_once_with`` fails. Patch by Petter Strandmark. 395 | 396 | - bpo-28380: unittest.mock Mock autospec functions now properly support 397 | assert_called, assert_not_called, and assert_called_once. 398 | 399 | - bpo-28735: Fixed the comparison of mock.MagickMock with mock.ANY. 400 | 401 | - bpo-20804: The unittest.mock.sentinel attributes now preserve their 402 | identity when they are copied or pickled. 403 | 404 | - bpo-28961: Fix unittest.mock._Call helper: don't ignore the name parameter 405 | anymore. Patch written by Jiajun Huang. 406 | 407 | - bpo-26750: unittest.mock.create_autospec() now works properly for 408 | subclasses of property() and other data descriptors. 409 | 410 | - bpo-21271: New keyword only parameters in reset_mock call. 411 | 412 | - bpo-26807: mock_open 'files' no longer error on readline at end of file. 413 | Patch from Yolanda Robla. 414 | 415 | - bpo-25195: Fix a regression in mock.MagicMock. _Call is a subclass of 416 | tuple (changeset 3603bae63c13 only works for classes) so we need to 417 | implement __ne__ ourselves. Patch by Andrew Plummer. 418 | 419 | 2.0.0 and earlier 420 | ----------------- 421 | 422 | - bpo-26323: Add Mock.assert_called() and Mock.assert_called_once() 423 | methods to unittest.mock. Patch written by Amit Saha. 424 | 425 | - bpo-22138: Fix mock.patch behavior when patching descriptors. Restore 426 | original values after patching. Patch contributed by Sean McCully. 427 | 428 | - bpo-24857: Comparing call_args to a long sequence now correctly returns a 429 | boolean result instead of raising an exception. Patch by A Kaptur. 430 | 431 | - bpo-23004: mock_open() now reads binary data correctly when the type of 432 | read_data is bytes. Initial patch by Aaron Hill. 433 | 434 | - bpo-21750: mock_open.read_data can now be read from each instance, as it 435 | could in Python 3.3. 436 | 437 | - bpo-18622: unittest.mock.mock_open().reset_mock would recurse infinitely. 438 | Patch from Nicola Palumbo and Laurent De Buyst. 439 | 440 | - bpo-23661: unittest.mock side_effects can now be exceptions again. This 441 | was a regression vs Python 3.4. Patch from Ignacio Rossi 442 | 443 | - bpo-23310: Fix MagicMock's initializer to work with __methods__, just 444 | like configure_mock(). Patch by Kasia Jachim. 445 | 446 | - bpo-23568: Add rdivmod support to MagicMock() objects. 447 | Patch by Håkan Lövdahl. 448 | 449 | - bpo-23581: Add matmul support to MagicMock. Patch by Håkan Lövdahl. 450 | 451 | - bpo-23326: Removed __ne__ implementations. Since fixing default __ne__ 452 | implementation in bpo-21408 they are redundant. *** NOT BACKPORTED *** 453 | 454 | - bpo-21270: We now override tuple methods in mock.call objects so that 455 | they can be used as normal call attributes. 456 | 457 | - bpo-21256: Printout of keyword args should be in deterministic order in 458 | a mock function call. This will help to write better doctests. 459 | 460 | - bpo-21262: New method assert_not_called for Mock. 461 | It raises AssertionError if the mock has been called. 462 | 463 | - bpo-21238: New keyword argument `unsafe` to Mock. It raises 464 | `AttributeError` incase of an attribute startswith assert or assret. 465 | 466 | - bpo-21239: patch.stopall() didn't work deterministically when the same 467 | name was patched more than once. 468 | 469 | - bpo-21222: Passing name keyword argument to mock.create_autospec now 470 | works. 471 | 472 | - bpo-17826: setting an iterable side_effect on a mock function created by 473 | create_autospec now works. Patch by Kushal Das. 474 | 475 | - bpo-17826: setting an iterable side_effect on a mock function created by 476 | create_autospec now works. Patch by Kushal Das. 477 | 478 | - bpo-20968: unittest.mock.MagicMock now supports division. 479 | Patch by Johannes Baiter. 480 | 481 | - bpo-20189: unittest.mock now no longer assumes that any object for 482 | which it could get an inspect.Signature is a callable written in Python. 483 | Fix courtesy of Michael Foord. 484 | 485 | - bpo-17467: add readline and readlines support to mock_open in 486 | unittest.mock. 487 | 488 | - bpo-17015: When it has a spec, a Mock object now inspects its signature 489 | when matching calls, so that arguments can be matched positionally or 490 | by name. 491 | 492 | - bpo-15323: improve failure message of Mock.assert_called_once_with 493 | 494 | - bpo-14857: fix regression in references to PEP 3135 implicit __class__ 495 | closure variable (Reopens bpo-12370) 496 | 497 | - bpo-14295: Add unittest.mock 498 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003-2013, Michael Foord & the mock team 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following 13 | disclaimer in the documentation and/or other materials provided 14 | with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.txt 2 | include *.rst 3 | recursive-include mock/tests *.py 4 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | mock is a library for testing in Python. It allows you to replace parts of 2 | your system under test with mock objects and make assertions about how they 3 | have been used. 4 | 5 | mock is now part of the Python standard library, available as `unittest.mock 6 | `_ in Python 3.3 7 | onwards. 8 | 9 | This package contains a rolling backport of the standard library mock code 10 | compatible with Python 3.6 and up. 11 | 12 | Please see the standard library documentation for more details. 13 | 14 | :Homepage: `Mock Homepage`_ 15 | :Download: `Mock on PyPI`_ 16 | :Documentation: `Python Docs`_ 17 | :License: `BSD License`_ 18 | :Support: `Mailing list (testing-in-python@lists.idyll.org) 19 | `_ 20 | :Code: `GitHub 21 | `_ 22 | :Issue tracker: `GitHub Issues 23 | `_ 24 | :Build status: 25 | |CircleCI|_ |Docs|_ 26 | 27 | .. |CircleCI| image:: https://circleci.com/gh/testing-cabal/mock/tree/master.svg?style=shield 28 | .. _CircleCI: https://circleci.com/gh/testing-cabal/mock/tree/master 29 | 30 | .. |Docs| image:: https://readthedocs.org/projects/mock/badge/?version=latest 31 | .. _Docs: http://mock.readthedocs.org/en/latest/ 32 | 33 | .. _Mock Homepage: http://mock.readthedocs.org/en/latest/ 34 | .. _BSD License: https://github.com/testing-cabal/mock/blob/master/LICENSE.txt 35 | .. _Python Docs: https://docs.python.org/dev/library/unittest.mock.html 36 | .. _mock on PyPI: https://pypi.org/project/mock/ 37 | -------------------------------------------------------------------------------- /backport.py: -------------------------------------------------------------------------------- 1 | import re 2 | from argparse import ArgumentParser 3 | from os.path import dirname, abspath, join 4 | from subprocess import check_output, call 5 | 6 | 7 | def git(command, repo): 8 | return check_output('git '+command, cwd=repo, shell=True).decode() 9 | 10 | 11 | def repo_state_bad(mock_repo): 12 | status = git('status', mock_repo) 13 | if 'You are in the middle of an am session' in status: 14 | print(f'Mock repo at {mock_repo} needs cleanup:\n') 15 | call('git status', shell=True) 16 | return True 17 | 18 | 19 | def cleanup_old_patches(mock_repo): 20 | print('cleaning up old patches:') 21 | call('rm -vf /tmp/*.mock.patch', shell=True) 22 | call('find . -name "*.rej" -print -delete', shell=True, cwd=mock_repo) 23 | 24 | 25 | def find_initial_cpython_rev(): 26 | with open('lastsync.txt') as source: 27 | return source.read().strip() 28 | 29 | 30 | def cpython_revs_affecting_mock(cpython_repo, start): 31 | revs = git(f'log --no-merges --format=%H {start}.. ' 32 | f'-- ' 33 | f'Lib/unittest/mock.py ' 34 | f'Lib/unittest/test/testmock/ ' 35 | f'Lib/test/test_unittest/testmock/', 36 | repo=cpython_repo).split() 37 | revs.reverse() 38 | print(f'{len(revs)} patches that may need backporting') 39 | return revs 40 | 41 | 42 | def has_been_backported(mock_repo, cpython_rev): 43 | backport_rev = git(f'log --format=%H --grep "Backports: {cpython_rev}"', 44 | repo=mock_repo).strip() 45 | if backport_rev: 46 | print(f'{cpython_rev} backported in {backport_rev}') 47 | return True 48 | print(f'{cpython_rev} has not been backported') 49 | 50 | 51 | def extract_patch_for(cpython_repo, rev): 52 | return git(f'format-patch -1 --no-stat --keep-subject --signoff --stdout {rev}', 53 | repo=cpython_repo) 54 | 55 | 56 | def munge(rev, patch): 57 | 58 | sign_off = 'Signed-off-by:' 59 | patch = patch.replace(sign_off, f'Backports: {rev}\n{sign_off}', 1) 60 | 61 | for pattern, sub in ( 62 | ('(a|b)/Lib/unittest/mock.py', r'\1/mock/mock.py'), 63 | (r'(a|b)/Lib/unittest/test/testmock/(\S+)', r'\1/mock/tests/\2'), 64 | (r'(a|b)/Lib/test/test_unittest/testmock/(\S+)', r'\1/mock/tests/\2'), 65 | ('(a|b)/Misc/NEWS', r'\1/NEWS'), 66 | ('(a|b)/NEWS.d/next/[^/]+/(.+\.rst)', r'\1/NEWS.d/\2'), 67 | ): 68 | patch = re.sub(pattern, sub, patch) 69 | return patch 70 | 71 | 72 | def apply_patch(mock_repo, rev, patch): 73 | patch_path = f'/tmp/{rev}.mock.patch' 74 | 75 | with open(patch_path, 'w') as target: 76 | target.write(patch) 77 | print(f'wrote {patch_path}') 78 | 79 | call(f'git am -k ' 80 | f'--include "mock/*" --include NEWS --include "NEWS.d/*" ' 81 | f'--reject {patch_path} ', 82 | cwd=mock_repo, shell=True) 83 | 84 | 85 | def update_last_sync(mock_repo, rev): 86 | with open(join(mock_repo, 'lastsync.txt'), 'w') as target: 87 | target.write(rev+'\n') 88 | print(f'update lastsync.txt to {rev}') 89 | 90 | 91 | def rev_from_mock_patch(text): 92 | match = re.search('Backports: ([a-z0-9]+)', text) 93 | return match.group(1) 94 | 95 | 96 | def skip_current(mock_repo, reason): 97 | text = git('am --show-current-patch', repo=mock_repo) 98 | rev = rev_from_mock_patch(text) 99 | git('am --abort', repo=mock_repo) 100 | print(f'skipping {rev}') 101 | update_last_sync(mock_repo, rev) 102 | call(f'git commit -m "Backports: {rev}, skipped: {reason}" lastsync.txt', shell=True, cwd=mock_repo) 103 | cleanup_old_patches(mock_repo) 104 | 105 | 106 | def commit_last_sync(revs, mock_repo): 107 | print('Yay! All caught up!') 108 | if len(revs): 109 | git('commit -m "latest sync point" lastsync.txt', repo=mock_repo) 110 | 111 | 112 | def main(): 113 | args = parse_args() 114 | 115 | if args.skip_current: 116 | return skip_current(args.mock, args.skip_reason) 117 | 118 | initial_cpython_rev = find_initial_cpython_rev() 119 | 120 | if args.list: 121 | for rev in cpython_revs_affecting_mock(args.cpython, initial_cpython_rev): 122 | print(git(f'show --name-only --oneline {rev}', args.cpython), end='') 123 | has_been_backported(args.mock, rev) 124 | print() 125 | return 126 | 127 | if repo_state_bad(args.mock): 128 | return 129 | 130 | cleanup_old_patches(args.mock) 131 | 132 | if args.rev: 133 | revs = [args.rev] 134 | else: 135 | revs = cpython_revs_affecting_mock(args.cpython, initial_cpython_rev) 136 | 137 | for rev in revs: 138 | 139 | if has_been_backported(args.mock, rev): 140 | update_last_sync(args.mock, rev) 141 | continue 142 | 143 | patch = extract_patch_for(args.cpython, rev) 144 | patch = munge(rev, patch) 145 | apply_patch(args.mock, rev, patch) 146 | break 147 | 148 | else: 149 | if not args.rev: 150 | commit_last_sync(revs, args.mock) 151 | 152 | 153 | def parse_args(): 154 | parser = ArgumentParser() 155 | parser.add_argument('--cpython', default='../cpython') 156 | parser.add_argument('--mock', default=abspath(dirname(__file__))) 157 | parser.add_argument('--list', action='store_true', help='list revs remaining to backport') 158 | parser.add_argument('--rev', help='backport a specific git hash') 159 | parser.add_argument('--skip-current', action='store_true') 160 | parser.add_argument('--skip-reason', default='it has no changes needed here.') 161 | return parser.parse_args() 162 | 163 | 164 | if __name__ == '__main__': 165 | main() 166 | -------------------------------------------------------------------------------- /docs/changelog.txt: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | .. include:: ../CHANGELOG.rst 5 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Mock documentation build configuration file, created by 4 | # sphinx-quickstart on Mon Nov 17 18:12:00 2008. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # The contents of this file are pickled, so don't put values in the namespace 9 | # that aren't pickleable (module imports are okay, they're removed automatically). 10 | # 11 | # All configuration values have a default value; values that are commented out 12 | # serve to show the default value. 13 | 14 | import sys, os 15 | sys.path.insert(0, os.path.abspath('..')) 16 | 17 | import mock 18 | 19 | # If your extensions are in another directory, add it here. If the directory 20 | # is relative to the documentation root, use os.path.abspath to make it 21 | # absolute, like shown here. 22 | #sys.path.append(os.path.abspath('some/directory')) 23 | 24 | # General configuration 25 | # --------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = [ 30 | 'sphinx.ext.intersphinx', 31 | ] 32 | 33 | intersphinx_mapping = { 34 | 'python': ('http://docs.python.org/dev', None), 35 | } 36 | 37 | doctest_global_setup = """ 38 | import os 39 | import sys 40 | import mock 41 | from mock import * # yeah, I know :-/ 42 | import __main__ 43 | 44 | if os.getcwd() not in sys.path: 45 | sys.path.append(os.getcwd()) 46 | 47 | # keep a reference to __main__ 48 | sys.modules['__main'] = __main__ 49 | 50 | class ProxyModule(object): 51 | def __init__(self): 52 | self.__dict__ = globals() 53 | 54 | sys.modules['__main__'] = ProxyModule() 55 | """ 56 | 57 | doctest_global_cleanup = """ 58 | sys.modules['__main__'] = sys.modules['__main'] 59 | """ 60 | 61 | html_theme = 'nature' 62 | html_theme_options = {} 63 | 64 | # Add any paths that contain templates here, relative to this directory. 65 | #templates_path = ['_templates'] 66 | 67 | # The suffix of source filenames. 68 | source_suffix = '.txt' 69 | 70 | # The master toctree document. 71 | master_doc = 'index' 72 | 73 | # General substitutions. 74 | project = u'Mock' 75 | copyright = u'2007-2015, Michael Foord & the mock team' 76 | 77 | # The default replacements for |version| and |release|, also used in various 78 | # other places throughout the built documents. Supplied by pbr. 79 | # 80 | version = release = mock.__version__ 81 | 82 | # There are two options for replacing |today|: either, you set today to some 83 | # non-false value, then it is used: (Set from pbr) 84 | today = '' 85 | # Else, today_fmt is used as the format for a strftime call. 86 | # today_fmt = '%B %d, %Y' 87 | 88 | # List of documents that shouldn't be included in the build. 89 | #unused_docs = [] 90 | 91 | # List of directories, relative to source directories, that shouldn't be searched 92 | # for source files. 93 | exclude_trees = [] 94 | 95 | # The reST default role (used for this markup: `text`) to use for all documents. 96 | #default_role = None 97 | 98 | # If true, '()' will be appended to :func: etc. cross-reference text. 99 | #add_function_parentheses = True 100 | 101 | # If true, the current module name will be prepended to all description 102 | # unit titles (such as .. function::). 103 | add_module_names = False 104 | 105 | # If true, sectionauthor and moduleauthor directives will be shown in the 106 | # output. They are ignored by default. 107 | #show_authors = False 108 | 109 | # The name of the Pygments (syntax highlighting) style to use. 110 | pygments_style = 'friendly' 111 | 112 | 113 | # Options for HTML output 114 | # ----------------------- 115 | 116 | # The style sheet to use for HTML and HTML Help pages. A file of that name 117 | # must exist either in Sphinx' static/ path, or in one of the custom paths 118 | # given in html_static_path. 119 | #html_style = 'adctheme.css' 120 | 121 | # The name for this set of Sphinx documents. If None, it defaults to 122 | # " v documentation". 123 | #html_title = None 124 | 125 | # A shorter title for the navigation bar. Default is the same as html_title. 126 | #html_short_title = None 127 | 128 | # The name of an image file (relative to this directory) to place at the top 129 | # of the sidebar. 130 | #html_logo = None 131 | 132 | # The name of an image file (within the static path) to use as favicon of the 133 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 134 | # pixels large. 135 | #html_favicon = None 136 | 137 | # Add any paths that contain custom static files (such as style sheets) here, 138 | # relative to this directory. They are copied after the builtin static files, 139 | # so a file named "default.css" will overwrite the builtin "default.css". 140 | #html_static_path = ['_static'] 141 | 142 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 143 | # using the given strftime format. 144 | html_last_updated_fmt = '%b %d, %Y' 145 | 146 | # If true, SmartyPants will be used to convert quotes and dashes to 147 | # typographically correct entities. 148 | #html_use_smartypants = True 149 | 150 | # Custom sidebar templates, maps document names to template names. 151 | #html_sidebars = {} 152 | 153 | # Additional templates that should be rendered to pages, maps page names to 154 | # template names. 155 | #html_additional_pages = {} 156 | 157 | # If false, no module index is generated. 158 | html_use_modindex = False 159 | 160 | # If false, no index is generated. 161 | #html_use_index = True 162 | 163 | # If true, the index is split into individual pages for each letter. 164 | #html_split_index = False 165 | 166 | # If true, the reST sources are included in the HTML build as _sources/. 167 | #html_copy_source = True 168 | 169 | # If true, an OpenSearch description file will be output, and all pages will 170 | # contain a tag referring to it. The value of this option must be the 171 | # base URL from which the finished HTML is served. 172 | #html_use_opensearch = '' 173 | 174 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 175 | #html_file_suffix = '' 176 | 177 | # Output file base name for HTML help builder. 178 | htmlhelp_basename = 'Mockdoc' 179 | 180 | 181 | # Options for LaTeX output 182 | # ------------------------ 183 | 184 | # The paper size ('letter' or 'a4'). 185 | #latex_paper_size = 'letter' 186 | 187 | # The font size ('10pt', '11pt' or '12pt'). 188 | latex_font_size = '12pt' 189 | 190 | # Grouping the document tree into LaTeX files. List of tuples 191 | # (source start file, target name, title, author, document class [howto/manual]). 192 | latex_documents = [ 193 | ('index', 'Mock.tex', u'Mock Documentation', 194 | u'Michael Foord', 'manual'), 195 | ] 196 | 197 | # The name of an image file (relative to this directory) to place at the top of 198 | # the title page. 199 | #latex_logo = None 200 | 201 | # For "manual" documents, if this is true, then toplevel headings are parts, 202 | # not chapters. 203 | #latex_use_parts = False 204 | 205 | # Additional stuff for the LaTeX preamble. 206 | #latex_preamble = '' 207 | 208 | # Documents to append as an appendix to all manuals. 209 | #latex_appendices = [] 210 | 211 | # If false, no module index is generated. 212 | latex_use_modindex = False 213 | -------------------------------------------------------------------------------- /docs/index.txt: -------------------------------------------------------------------------------- 1 | =================================== 2 | Mock - Mocking and Testing Library 3 | =================================== 4 | 5 | .. include:: ../README.rst 6 | 7 | .. module:: mock 8 | :synopsis: Mock object and testing library. 9 | 10 | .. index:: introduction 11 | 12 | .. toctree:: 13 | :hidden: 14 | 15 | changelog 16 | 17 | Python Version Compatibility 18 | ++++++++++++++++++++++++++++ 19 | 20 | * Version 1.0.1 is the last version compatible with Python < 2.6. 21 | 22 | * Version 1.3.0 is the last version compatible with Python 3.2. 23 | 24 | * Version 2.0.0 is the last version compatible with Python 2.6. 25 | 26 | * Version 2.0.0 is the last version offering official Jython support. 27 | 28 | * version 3.0.5 is the last version supporting Python 3.5 and lower. 29 | 30 | .. index:: installing 31 | .. _installing: 32 | 33 | Installing 34 | ++++++++++ 35 | 36 | .. index:: repository 37 | .. index:: git 38 | 39 | You can checkout the latest development version from GitHub 40 | repository with the following command: 41 | 42 | ``git clone https://github.com/testing-cabal/mock.git`` 43 | 44 | 45 | .. index:: pip 46 | 47 | You can install mock with pip: 48 | 49 | | ``pip install -U mock`` 50 | 51 | .. index:: bug reports 52 | 53 | Bug Reports 54 | +++++++++++ 55 | 56 | Issues with the backport process, such as compatibility with a particular 57 | Python, should be reported to the `bug tracker 58 | `_. Feature requests and issues 59 | with Mock functionality should be reported to the `Python bug tracker 60 | `_. 61 | 62 | .. index:: python changes 63 | 64 | Changelog 65 | +++++++++ 66 | 67 | See the :doc:`change log `. 68 | 69 | .. index:: maintainer notes 70 | 71 | Maintainer Notes 72 | ++++++++++++++++ 73 | 74 | Development 75 | ----------- 76 | 77 | Checkout from git (see :ref:`installing`) and submit pull requests. 78 | 79 | Committers can just push as desired: since all semantic development takes 80 | place in cPython, the backport process is as lightweight as we can make it. 81 | 82 | If you end up fixing anything backport-specific, please add an entry 83 | to the top of ``CHANGELOG.rst`` so it shows up in the next release 84 | notes. 85 | 86 | Releasing 87 | --------- 88 | 89 | NB: please use semver. Bump the major component on API breaks, minor on all 90 | non-bugfix changes, patch on bugfix only changes. 91 | 92 | 1. Run ``release.py [major|minor|bugfix]`` which will roll out new 93 | NEWS items, bump the version number and create a commit for the release. 94 | 95 | 2. Review that commit, feel free to amend it if you want to note anything 96 | manually in ``CHANGELOG.rst``. 97 | 98 | 3. Push to the ``master`` branch on 99 | https://github.com/testing-cabal/mock.git and the Circle CI 100 | automation will take care of pushing releases to PyPI and 101 | creating a tag. 102 | 103 | Backporting rules 104 | ----------------- 105 | 106 | - If code such as this causes coverage checking to drop below 100%: 107 | 108 | .. code-block:: python 109 | 110 | def will_never_be_called(): 111 | pass 112 | 113 | It should be adjusted to the following pattern, preferably upstream, 114 | so that the ``.coveragerc`` in this repo knows to ignore it: 115 | 116 | .. code-block:: python 117 | 118 | def will_never_be_called(): 119 | pass # pragma: no cover 120 | 121 | - If code such as this causes coverage checking to drop below 100%: 122 | 123 | .. code-block:: python 124 | 125 | def will_never_be_called(): 126 | yield 127 | 128 | It should be adjusted to the following pattern, preferably upstream, 129 | so that the ``.coveragerc`` in this repo knows to ignore it: 130 | 131 | .. code-block:: python 132 | 133 | def will_never_be_called(): 134 | yield # pragma: no cover 135 | 136 | - If a backported patch applies cleanly, but ends up needing to be skipped, 137 | then commit the latest sync point and then revert the problematic commit in an immediately 138 | subsequent commit and make a note of the reason for the revert in that commit message. 139 | 140 | See `bc04ea7`__ for an example where `f4c8dc7`__ broke compatibility for all Python 141 | versions earlier than 3.10. 142 | 143 | __ https://github.com/testing-cabal/mock/commit/bc04ea76352c2064d79160f13649f879667a89cb 144 | 145 | __ https://github.com/testing-cabal/mock/commit/f4c8dc7098abb6b2f9a65ee86bad3891776abb50 146 | 147 | 148 | Backporting process 149 | ------------------- 150 | 151 | 1. Clone cpython and mock into the same directory, eg: 152 | 153 | .. code-block:: bash 154 | 155 | mkdir vcs 156 | cd vcs 157 | git clone https://github.com/python/cpython.git 158 | git clone https://github.com/testing-cabal/mock.git 159 | 160 | Make sure ``cpython` is on ``main` and that ``main`` branch is fully up to date! 161 | Make sure ``mock`` is on master and up fully up to date! 162 | 163 | 2. Create a branch in your ``mock`` clone and switch to it. 164 | 165 | 3. Make sure you build a suitable virtualenv for Mock development 166 | and activate it. For backporting, this should use Python 3.7+. 167 | 168 | 4. Run ``backport.py``: 169 | 170 | .. code-block:: bash 171 | 172 | cd vcs/mock 173 | python backport.py 174 | 175 | This will find the next cpython patch that needs to be applied, munge it 176 | and attempt to apply it with ``git am``. 177 | 178 | If it succeeds, run the tests and/or push your branch up to a fork and 179 | do a pull request into the master branch of the main repo to kick off 180 | the continuous integration tests. 181 | 182 | If it fails, you'll have to manually work with what ``git status`` shows 183 | to get the patch committed. 184 | 185 | If it turns out that there's nothing that should be applied from the failed commit, 186 | run ``python backport.py --skip-current``, maybe with ``--skip-reason``. 187 | 188 | If you have to make changes, please do a ``git commit --amend`` and add notes 189 | about what needed doing below the ``Signed-off-by`` block. 190 | 191 | If you have to make changes because tests fail with an applied patch, please 192 | make those changes in a followup commit and take note of the "Backporting rules" 193 | above. 194 | 195 | 5. Rinse and repeat until ``backport.py`` reports no more patches need applying. 196 | 197 | 6. If ``backport.py`` has updated ``lastsync.txt`` but not committed it, 198 | now would be a good time to commit that change. 199 | 200 | Checking coverage in upstream 201 | ----------------------------- 202 | 203 | Assuming you have the checkout structure as above, and you have compiled your cpython 204 | master branch, then roughly as follows: 205 | 206 | .. code-block:: bash 207 | 208 | ~/vcs/cpython/python.exe -m venv ~/virtualenvs/cpython-master 209 | source ~/virtualenvs/cpython-master/bin/activate 210 | pip install -U setuptools pip 211 | pip install pytest pytest-cov 212 | cd vcs/cpython/Lib/unittest 213 | pytest --cov unittest.mock --cov unittest.test.testmock \ 214 | --cov-config ~/vcs/git/mock/.coveragerc \ 215 | --cov-report term-missing:skip-covered \ 216 | test/testmock/test* 217 | 218 | Ignore ``test/testmock/__*__.py`` as these aren't present in the backport. 219 | -------------------------------------------------------------------------------- /lastsync.txt: -------------------------------------------------------------------------------- 1 | 04091c083340dde7d4eeb6d945c70f3b37d88f85 2 | -------------------------------------------------------------------------------- /mock/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | import re, sys 4 | 5 | IS_PYPY = 'PyPy' in sys.version 6 | 7 | import mock.mock as _mock 8 | from mock.mock import * 9 | 10 | __version__ = '5.2.0' 11 | version_info = tuple(int(p) for p in 12 | re.match(r'(\d+).(\d+).(\d+)', __version__).groups()) 13 | 14 | 15 | __all__ = ('__version__', 'version_info') + _mock.__all__ 16 | -------------------------------------------------------------------------------- /mock/backports.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | if sys.version_info[:2] > (3, 9): 5 | from inspect import iscoroutinefunction 6 | elif sys.version_info[:2] >= (3, 8): 7 | from asyncio import iscoroutinefunction 8 | else: 9 | 10 | import functools 11 | from asyncio.coroutines import _is_coroutine 12 | from inspect import ismethod, isfunction, CO_COROUTINE 13 | 14 | def _unwrap_partial(func): 15 | while isinstance(func, functools.partial): 16 | func = func.func 17 | return func 18 | 19 | def _has_code_flag(f, flag): 20 | """Return true if ``f`` is a function (or a method or functools.partial 21 | wrapper wrapping a function) whose code object has the given ``flag`` 22 | set in its flags.""" 23 | while ismethod(f): 24 | f = f.__func__ 25 | f = _unwrap_partial(f) 26 | if not isfunction(f): 27 | return False 28 | return bool(f.__code__.co_flags & flag) 29 | 30 | def iscoroutinefunction(obj): 31 | """Return true if the object is a coroutine function. 32 | 33 | Coroutine functions are defined with "async def" syntax. 34 | """ 35 | return ( 36 | _has_code_flag(obj, CO_COROUTINE) or 37 | getattr(obj, '_is_coroutine', None) is _is_coroutine 38 | ) 39 | 40 | 41 | try: 42 | from unittest import IsolatedAsyncioTestCase 43 | except ImportError: 44 | import asyncio 45 | from unittest import TestCase 46 | 47 | 48 | class IsolatedAsyncioTestCase(TestCase): 49 | 50 | def __init__(self, methodName='runTest'): 51 | super().__init__(methodName) 52 | self._asyncioTestLoop = None 53 | self._asyncioCallsQueue = None 54 | 55 | async def _asyncioLoopRunner(self, fut): 56 | self._asyncioCallsQueue = queue = asyncio.Queue() 57 | fut.set_result(None) 58 | while True: 59 | query = await queue.get() 60 | queue.task_done() 61 | assert query is None 62 | 63 | def _setupAsyncioLoop(self): 64 | assert self._asyncioTestLoop is None 65 | loop = asyncio.new_event_loop() 66 | asyncio.set_event_loop(loop) 67 | loop.set_debug(True) 68 | self._asyncioTestLoop = loop 69 | fut = loop.create_future() 70 | self._asyncioCallsTask = loop.create_task(self._asyncioLoopRunner(fut)) 71 | loop.run_until_complete(fut) 72 | 73 | def _tearDownAsyncioLoop(self): 74 | assert self._asyncioTestLoop is not None 75 | loop = self._asyncioTestLoop 76 | self._asyncioTestLoop = None 77 | self._asyncioCallsQueue.put_nowait(None) 78 | loop.run_until_complete(self._asyncioCallsQueue.join()) 79 | 80 | try: 81 | # shutdown asyncgens 82 | loop.run_until_complete(loop.shutdown_asyncgens()) 83 | finally: 84 | asyncio.set_event_loop(None) 85 | loop.close() 86 | 87 | def run(self, result=None): 88 | self._setupAsyncioLoop() 89 | try: 90 | return super().run(result) 91 | finally: 92 | self._tearDownAsyncioLoop() 93 | 94 | 95 | try: 96 | from asyncio import _set_event_loop_policy as set_event_loop_policy 97 | except ImportError: 98 | from asyncio import set_event_loop_policy 99 | -------------------------------------------------------------------------------- /mock/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/testing-cabal/mock/0f5df822bde4729cb2190819ad01a8728ddc9de3/mock/tests/__init__.py -------------------------------------------------------------------------------- /mock/tests/support.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import sys 3 | 4 | target = {'foo': 'FOO'} 5 | 6 | 7 | def is_instance(obj, klass): 8 | """Version of is_instance that doesn't access __class__""" 9 | return issubclass(type(obj), klass) 10 | 11 | 12 | class SomeClass(object): 13 | class_attribute = None 14 | 15 | def wibble(self): pass 16 | 17 | 18 | class X(object): 19 | pass 20 | 21 | # A standin for weurkzeug.local.LocalProxy - issue 119600 22 | def _inaccessible(*args, **kwargs): 23 | raise AttributeError 24 | 25 | 26 | class OpaqueProxy: 27 | __getattribute__ = _inaccessible 28 | 29 | 30 | g = OpaqueProxy() 31 | 32 | 33 | @contextlib.contextmanager 34 | def uncache(*names): 35 | """Uncache a module from sys.modules. 36 | 37 | A basic sanity check is performed to prevent uncaching modules that either 38 | cannot/shouldn't be uncached. 39 | 40 | """ 41 | for name in names: 42 | assert name not in ('sys', 'marshal', 'imp') 43 | try: 44 | del sys.modules[name] 45 | except KeyError: 46 | pass 47 | try: 48 | yield 49 | finally: 50 | for name in names: 51 | del sys.modules[name] 52 | 53 | 54 | class _ALWAYS_EQ: 55 | """ 56 | Object that is equal to anything. 57 | """ 58 | def __eq__(self, other): 59 | return True 60 | def __ne__(self, other): 61 | return False 62 | 63 | ALWAYS_EQ = _ALWAYS_EQ() 64 | -------------------------------------------------------------------------------- /mock/tests/testasync.py: -------------------------------------------------------------------------------- 1 | 2 | import asyncio 3 | import gc 4 | import inspect 5 | import re 6 | import unittest 7 | from contextlib import contextmanager 8 | 9 | from mock import (ANY, call, AsyncMock, patch, MagicMock, Mock, 10 | create_autospec, sentinel, seal) 11 | from mock.backports import IsolatedAsyncioTestCase, iscoroutinefunction, set_event_loop_policy 12 | from mock.mock import _CallList 13 | 14 | 15 | try: 16 | from asyncio import run 17 | except ImportError: 18 | def run(main): 19 | loop = asyncio.new_event_loop() 20 | try: 21 | return_value = loop.run_until_complete(main) 22 | finally: 23 | loop.close() 24 | return return_value 25 | 26 | 27 | def tearDownModule(): 28 | set_event_loop_policy(None) 29 | 30 | 31 | class AsyncClass: 32 | def __init__(self): pass 33 | async def async_method(self): pass 34 | def normal_method(self): pass 35 | 36 | @classmethod 37 | async def async_class_method(cls): pass 38 | 39 | @staticmethod 40 | async def async_static_method(): pass 41 | 42 | 43 | class AwaitableClass: 44 | def __await__(self): yield 45 | 46 | async def async_func(): pass 47 | 48 | async def async_func_args(a, b, *, c): pass 49 | 50 | def normal_func(): pass 51 | 52 | class NormalClass(object): 53 | def a(self): pass 54 | 55 | 56 | async_foo_name = f'{__name__}.AsyncClass' 57 | normal_foo_name = f'{__name__}.NormalClass' 58 | 59 | 60 | @contextmanager 61 | def assertNeverAwaited(test): 62 | with test.assertWarnsRegex(RuntimeWarning, "was never awaited$"): 63 | yield 64 | # In non-CPython implementations of Python, this is needed because timely 65 | # deallocation is not guaranteed by the garbage collector. 66 | gc.collect() 67 | 68 | 69 | class AsyncPatchDecoratorTest(unittest.TestCase): 70 | def test_is_coroutine_function_patch(self): 71 | @patch.object(AsyncClass, 'async_method') 72 | def test_async(mock_method): 73 | self.assertTrue(iscoroutinefunction(mock_method)) 74 | test_async() 75 | 76 | def test_is_async_patch(self): 77 | @patch.object(AsyncClass, 'async_method') 78 | def test_async(mock_method): 79 | m = mock_method() 80 | self.assertTrue(inspect.isawaitable(m)) 81 | run(m) 82 | 83 | @patch(f'{async_foo_name}.async_method') 84 | def test_no_parent_attribute(mock_method): 85 | m = mock_method() 86 | self.assertTrue(inspect.isawaitable(m)) 87 | run(m) 88 | 89 | test_async() 90 | test_no_parent_attribute() 91 | 92 | def test_is_AsyncMock_patch(self): 93 | @patch.object(AsyncClass, 'async_method') 94 | def test_async(mock_method): 95 | self.assertIsInstance(mock_method, AsyncMock) 96 | 97 | test_async() 98 | 99 | def test_is_AsyncMock_patch_staticmethod(self): 100 | @patch.object(AsyncClass, 'async_static_method') 101 | def test_async(mock_method): 102 | self.assertIsInstance(mock_method, AsyncMock) 103 | 104 | test_async() 105 | 106 | def test_is_AsyncMock_patch_classmethod(self): 107 | @patch.object(AsyncClass, 'async_class_method') 108 | def test_async(mock_method): 109 | self.assertIsInstance(mock_method, AsyncMock) 110 | 111 | test_async() 112 | 113 | def test_async_def_patch(self): 114 | @patch(f"{__name__}.async_func", return_value=1) 115 | @patch(f"{__name__}.async_func_args", return_value=2) 116 | async def test_async(func_args_mock, func_mock): 117 | self.assertEqual(func_args_mock._mock_name, "async_func_args") 118 | self.assertEqual(func_mock._mock_name, "async_func") 119 | 120 | self.assertIsInstance(async_func, AsyncMock) 121 | self.assertIsInstance(async_func_args, AsyncMock) 122 | 123 | self.assertEqual(await async_func(), 1) 124 | self.assertEqual(await async_func_args(1, 2, c=3), 2) 125 | 126 | run(test_async()) 127 | self.assertTrue(inspect.iscoroutinefunction(async_func)) 128 | 129 | 130 | class AsyncPatchCMTest(unittest.TestCase): 131 | def test_is_async_function_cm(self): 132 | def test_async(): 133 | with patch.object(AsyncClass, 'async_method') as mock_method: 134 | self.assertTrue(iscoroutinefunction(mock_method)) 135 | 136 | test_async() 137 | 138 | def test_is_async_cm(self): 139 | def test_async(): 140 | with patch.object(AsyncClass, 'async_method') as mock_method: 141 | m = mock_method() 142 | self.assertTrue(inspect.isawaitable(m)) 143 | run(m) 144 | 145 | test_async() 146 | 147 | def test_is_AsyncMock_cm(self): 148 | def test_async(): 149 | with patch.object(AsyncClass, 'async_method') as mock_method: 150 | self.assertIsInstance(mock_method, AsyncMock) 151 | 152 | test_async() 153 | 154 | def test_async_def_cm(self): 155 | async def test_async(): 156 | with patch(f"{__name__}.async_func", AsyncMock()): 157 | self.assertIsInstance(async_func, AsyncMock) 158 | self.assertTrue(inspect.iscoroutinefunction(async_func)) 159 | 160 | run(test_async()) 161 | 162 | def test_patch_dict_async_def(self): 163 | foo = {'a': 'a'} 164 | @patch.dict(foo, {'a': 'b'}) 165 | async def test_async(): 166 | self.assertEqual(foo['a'], 'b') 167 | 168 | self.assertTrue(iscoroutinefunction(test_async)) 169 | run(test_async()) 170 | 171 | def test_patch_dict_async_def_context(self): 172 | foo = {'a': 'a'} 173 | async def test_async(): 174 | with patch.dict(foo, {'a': 'b'}): 175 | self.assertEqual(foo['a'], 'b') 176 | 177 | run(test_async()) 178 | 179 | 180 | class AsyncMockTest(unittest.TestCase): 181 | def test_iscoroutinefunction_default(self): 182 | mock = AsyncMock() 183 | self.assertTrue(iscoroutinefunction(mock)) 184 | 185 | def test_iscoroutinefunction_function(self): 186 | async def foo(): pass 187 | mock = AsyncMock(foo) 188 | self.assertTrue(iscoroutinefunction(mock)) 189 | self.assertTrue(inspect.iscoroutinefunction(mock)) 190 | 191 | def test_isawaitable(self): 192 | mock = AsyncMock() 193 | m = mock() 194 | self.assertTrue(inspect.isawaitable(m)) 195 | run(m) 196 | self.assertIn('assert_awaited', dir(mock)) 197 | 198 | def test_iscoroutinefunction_normal_function(self): 199 | def foo(): pass 200 | mock = AsyncMock(foo) 201 | self.assertTrue(iscoroutinefunction(mock)) 202 | self.assertTrue(inspect.iscoroutinefunction(mock)) 203 | 204 | def test_future_isfuture(self): 205 | loop = asyncio.new_event_loop() 206 | fut = loop.create_future() 207 | loop.stop() 208 | loop.close() 209 | mock = AsyncMock(fut) 210 | self.assertIsInstance(mock, asyncio.Future) 211 | 212 | 213 | class AsyncAutospecTest(unittest.TestCase): 214 | def test_is_AsyncMock_patch(self): 215 | @patch(async_foo_name, autospec=True) 216 | def test_async(mock_method): 217 | self.assertIsInstance(mock_method.async_method, AsyncMock) 218 | self.assertIsInstance(mock_method, MagicMock) 219 | 220 | @patch(async_foo_name, autospec=True) 221 | def test_normal_method(mock_method): 222 | self.assertIsInstance(mock_method.normal_method, MagicMock) 223 | 224 | test_async() 225 | test_normal_method() 226 | 227 | def test_create_autospec_instance(self): 228 | with self.assertRaises(RuntimeError): 229 | create_autospec(async_func, instance=True) 230 | 231 | def test_create_autospec(self): 232 | spec = create_autospec(async_func_args) 233 | awaitable = spec(1, 2, c=3) 234 | async def main(): 235 | await awaitable 236 | 237 | self.assertEqual(spec.await_count, 0) 238 | self.assertIsNone(spec.await_args) 239 | self.assertEqual(spec.await_args_list, []) 240 | spec.assert_not_awaited() 241 | 242 | run(main()) 243 | 244 | self.assertTrue(iscoroutinefunction(spec)) 245 | self.assertTrue(inspect.iscoroutinefunction(spec)) 246 | self.assertTrue(asyncio.iscoroutine(awaitable)) 247 | self.assertTrue(inspect.iscoroutine(awaitable)) 248 | self.assertEqual(spec.await_count, 1) 249 | self.assertEqual(spec.await_args, call(1, 2, c=3)) 250 | self.assertEqual(spec.await_args_list, [call(1, 2, c=3)]) 251 | spec.assert_awaited_once() 252 | spec.assert_awaited_once_with(1, 2, c=3) 253 | spec.assert_awaited_with(1, 2, c=3) 254 | spec.assert_awaited() 255 | 256 | with self.assertRaises(AssertionError): 257 | spec.assert_any_await(e=1) 258 | 259 | def test_autospec_checks_signature(self): 260 | spec = create_autospec(async_func_args) 261 | # signature is not checked when called 262 | awaitable = spec() 263 | self.assertListEqual(spec.mock_calls, []) 264 | 265 | async def main(): 266 | await awaitable 267 | 268 | # but it is checked when awaited 269 | with self.assertRaises(TypeError): 270 | run(main()) 271 | 272 | # _checksig_ raises before running or awaiting the mock 273 | self.assertListEqual(spec.mock_calls, []) 274 | self.assertEqual(spec.await_count, 0) 275 | self.assertIsNone(spec.await_args) 276 | self.assertEqual(spec.await_args_list, []) 277 | spec.assert_not_awaited() 278 | 279 | def test_patch_with_autospec(self): 280 | 281 | async def test_async(): 282 | with patch(f"{__name__}.async_func_args", autospec=True) as mock_method: 283 | awaitable = mock_method(1, 2, c=3) 284 | self.assertIsInstance(mock_method.mock, AsyncMock) 285 | 286 | self.assertTrue(iscoroutinefunction(mock_method)) 287 | self.assertTrue(inspect.iscoroutinefunction(mock_method)) 288 | self.assertTrue(asyncio.iscoroutine(awaitable)) 289 | self.assertTrue(inspect.iscoroutine(awaitable)) 290 | self.assertTrue(inspect.isawaitable(awaitable)) 291 | 292 | # Verify the default values during mock setup 293 | self.assertEqual(mock_method.await_count, 0) 294 | self.assertEqual(mock_method.await_args_list, []) 295 | self.assertIsNone(mock_method.await_args) 296 | mock_method.assert_not_awaited() 297 | 298 | await awaitable 299 | 300 | self.assertEqual(mock_method.await_count, 1) 301 | self.assertEqual(mock_method.await_args, call(1, 2, c=3)) 302 | self.assertEqual(mock_method.await_args_list, [call(1, 2, c=3)]) 303 | mock_method.assert_awaited_once() 304 | mock_method.assert_awaited_once_with(1, 2, c=3) 305 | mock_method.assert_awaited_with(1, 2, c=3) 306 | mock_method.assert_awaited() 307 | 308 | mock_method.reset_mock() 309 | self.assertEqual(mock_method.await_count, 0) 310 | self.assertIsNone(mock_method.await_args) 311 | self.assertEqual(mock_method.await_args_list, []) 312 | 313 | run(test_async()) 314 | 315 | 316 | class AsyncSpecTest(unittest.TestCase): 317 | def test_spec_normal_methods_on_class(self): 318 | def inner_test(mock_type): 319 | mock = mock_type(AsyncClass) 320 | self.assertIsInstance(mock.async_method, AsyncMock) 321 | self.assertIsInstance(mock.normal_method, MagicMock) 322 | 323 | for mock_type in [AsyncMock, MagicMock]: 324 | with self.subTest(f"test method types with {mock_type}"): 325 | inner_test(mock_type) 326 | 327 | def test_spec_normal_methods_on_class_with_mock(self): 328 | mock = Mock(AsyncClass) 329 | self.assertIsInstance(mock.async_method, AsyncMock) 330 | self.assertIsInstance(mock.normal_method, Mock) 331 | 332 | def test_spec_normal_methods_on_class_with_mock_seal(self): 333 | mock = Mock(AsyncClass) 334 | seal(mock) 335 | with self.assertRaises(AttributeError): 336 | mock.normal_method 337 | with self.assertRaises(AttributeError): 338 | mock.async_method 339 | 340 | def test_spec_async_attributes_instance(self): 341 | async_instance = AsyncClass() 342 | async_instance.async_func_attr = async_func 343 | async_instance.later_async_func_attr = normal_func 344 | 345 | mock_async_instance = Mock(spec_set=async_instance) 346 | 347 | async_instance.later_async_func_attr = async_func 348 | 349 | self.assertIsInstance(mock_async_instance.async_func_attr, AsyncMock) 350 | # only the shape of the spec at the time of mock construction matters 351 | self.assertNotIsInstance(mock_async_instance.later_async_func_attr, AsyncMock) 352 | 353 | def test_spec_mock_type_kw(self): 354 | def inner_test(mock_type): 355 | async_mock = mock_type(spec=async_func) 356 | self.assertIsInstance(async_mock, mock_type) 357 | with assertNeverAwaited(self): 358 | self.assertTrue(inspect.isawaitable(async_mock())) 359 | 360 | sync_mock = mock_type(spec=normal_func) 361 | self.assertIsInstance(sync_mock, mock_type) 362 | 363 | for mock_type in [AsyncMock, MagicMock, Mock]: 364 | with self.subTest(f"test spec kwarg with {mock_type}"): 365 | inner_test(mock_type) 366 | 367 | def test_spec_mock_type_positional(self): 368 | def inner_test(mock_type): 369 | async_mock = mock_type(async_func) 370 | self.assertIsInstance(async_mock, mock_type) 371 | with assertNeverAwaited(self): 372 | self.assertTrue(inspect.isawaitable(async_mock())) 373 | 374 | sync_mock = mock_type(normal_func) 375 | self.assertIsInstance(sync_mock, mock_type) 376 | 377 | for mock_type in [AsyncMock, MagicMock, Mock]: 378 | with self.subTest(f"test spec positional with {mock_type}"): 379 | inner_test(mock_type) 380 | 381 | def test_spec_as_normal_kw_AsyncMock(self): 382 | mock = AsyncMock(spec=normal_func) 383 | self.assertIsInstance(mock, AsyncMock) 384 | m = mock() 385 | self.assertTrue(inspect.isawaitable(m)) 386 | run(m) 387 | 388 | def test_spec_as_normal_positional_AsyncMock(self): 389 | mock = AsyncMock(normal_func) 390 | self.assertIsInstance(mock, AsyncMock) 391 | m = mock() 392 | self.assertTrue(inspect.isawaitable(m)) 393 | run(m) 394 | 395 | def test_spec_async_mock(self): 396 | @patch.object(AsyncClass, 'async_method', spec=True) 397 | def test_async(mock_method): 398 | self.assertIsInstance(mock_method, AsyncMock) 399 | 400 | test_async() 401 | 402 | def test_spec_parent_not_async_attribute_is(self): 403 | @patch(async_foo_name, spec=True) 404 | def test_async(mock_method): 405 | self.assertIsInstance(mock_method, MagicMock) 406 | self.assertIsInstance(mock_method.async_method, AsyncMock) 407 | 408 | test_async() 409 | 410 | def test_target_async_spec_not(self): 411 | @patch.object(AsyncClass, 'async_method', spec=NormalClass.a) 412 | def test_async_attribute(mock_method): 413 | self.assertIsInstance(mock_method, MagicMock) 414 | self.assertFalse(inspect.iscoroutine(mock_method)) 415 | self.assertFalse(inspect.isawaitable(mock_method)) 416 | 417 | test_async_attribute() 418 | 419 | def test_target_not_async_spec_is(self): 420 | @patch.object(NormalClass, 'a', spec=async_func) 421 | def test_attribute_not_async_spec_is(mock_async_func): 422 | self.assertIsInstance(mock_async_func, AsyncMock) 423 | test_attribute_not_async_spec_is() 424 | 425 | def test_spec_async_attributes(self): 426 | @patch(normal_foo_name, spec=AsyncClass) 427 | def test_async_attributes_coroutines(MockNormalClass): 428 | self.assertIsInstance(MockNormalClass.async_method, AsyncMock) 429 | self.assertIsInstance(MockNormalClass, MagicMock) 430 | 431 | test_async_attributes_coroutines() 432 | 433 | 434 | class AsyncSpecSetTest(unittest.TestCase): 435 | def test_is_AsyncMock_patch(self): 436 | @patch.object(AsyncClass, 'async_method', spec_set=True) 437 | def test_async(async_method): 438 | self.assertIsInstance(async_method, AsyncMock) 439 | test_async() 440 | 441 | def test_is_async_AsyncMock(self): 442 | mock = AsyncMock(spec_set=AsyncClass.async_method) 443 | self.assertTrue(iscoroutinefunction(mock)) 444 | self.assertIsInstance(mock, AsyncMock) 445 | 446 | def test_is_child_AsyncMock(self): 447 | mock = MagicMock(spec_set=AsyncClass) 448 | self.assertTrue(iscoroutinefunction(mock.async_method)) 449 | self.assertFalse(iscoroutinefunction(mock.normal_method)) 450 | self.assertIsInstance(mock.async_method, AsyncMock) 451 | self.assertIsInstance(mock.normal_method, MagicMock) 452 | self.assertIsInstance(mock, MagicMock) 453 | 454 | def test_magicmock_lambda_spec(self): 455 | mock_obj = MagicMock() 456 | mock_obj.mock_func = MagicMock(spec=lambda x: x) 457 | 458 | with patch.object(mock_obj, "mock_func") as cm: 459 | self.assertIsInstance(cm, MagicMock) 460 | 461 | 462 | class AsyncArguments(IsolatedAsyncioTestCase): 463 | async def test_add_return_value(self): 464 | async def addition(self, var): pass 465 | 466 | mock = AsyncMock(addition, return_value=10) 467 | output = await mock(5) 468 | 469 | self.assertEqual(output, 10) 470 | 471 | async def test_add_side_effect_exception(self): 472 | class CustomError(Exception): pass 473 | async def addition(var): pass 474 | mock = AsyncMock(addition, side_effect=CustomError('side-effect')) 475 | with self.assertRaisesRegex(CustomError, 'side-effect'): 476 | await mock(5) 477 | 478 | async def test_add_side_effect_coroutine(self): 479 | async def addition(var): 480 | return var + 1 481 | mock = AsyncMock(side_effect=addition) 482 | result = await mock(5) 483 | self.assertEqual(result, 6) 484 | 485 | async def test_add_side_effect_normal_function(self): 486 | def addition(var): 487 | return var + 1 488 | mock = AsyncMock(side_effect=addition) 489 | result = await mock(5) 490 | self.assertEqual(result, 6) 491 | 492 | async def test_add_side_effect_iterable(self): 493 | vals = [1, 2, 3] 494 | mock = AsyncMock(side_effect=vals) 495 | for item in vals: 496 | self.assertEqual(await mock(), item) 497 | 498 | with self.assertRaises(StopAsyncIteration) as e: 499 | await mock() 500 | 501 | async def test_add_side_effect_exception_iterable(self): 502 | class SampleException(Exception): 503 | pass 504 | 505 | vals = [1, SampleException("foo")] 506 | mock = AsyncMock(side_effect=vals) 507 | self.assertEqual(await mock(), 1) 508 | 509 | with self.assertRaises(SampleException) as e: 510 | await mock() 511 | 512 | async def test_return_value_AsyncMock(self): 513 | value = AsyncMock(return_value=10) 514 | mock = AsyncMock(return_value=value) 515 | result = await mock() 516 | self.assertIs(result, value) 517 | 518 | async def test_return_value_awaitable(self): 519 | fut = asyncio.Future() 520 | fut.set_result(None) 521 | mock = AsyncMock(return_value=fut) 522 | result = await mock() 523 | self.assertIsInstance(result, asyncio.Future) 524 | 525 | async def test_side_effect_awaitable_values(self): 526 | fut = asyncio.Future() 527 | fut.set_result(None) 528 | 529 | mock = AsyncMock(side_effect=[fut]) 530 | result = await mock() 531 | self.assertIsInstance(result, asyncio.Future) 532 | 533 | with self.assertRaises(StopAsyncIteration): 534 | await mock() 535 | 536 | async def test_side_effect_is_AsyncMock(self): 537 | effect = AsyncMock(return_value=10) 538 | mock = AsyncMock(side_effect=effect) 539 | 540 | result = await mock() 541 | self.assertEqual(result, 10) 542 | 543 | async def test_wraps_coroutine(self): 544 | value = asyncio.Future() 545 | 546 | ran = False 547 | async def inner(): 548 | nonlocal ran 549 | ran = True 550 | return value 551 | 552 | mock = AsyncMock(wraps=inner) 553 | result = await mock() 554 | self.assertEqual(result, value) 555 | mock.assert_awaited() 556 | self.assertTrue(ran) 557 | 558 | async def test_wraps_normal_function(self): 559 | value = 1 560 | 561 | ran = False 562 | def inner(): 563 | nonlocal ran 564 | ran = True 565 | return value 566 | 567 | mock = AsyncMock(wraps=inner) 568 | result = await mock() 569 | self.assertEqual(result, value) 570 | mock.assert_awaited() 571 | self.assertTrue(ran) 572 | 573 | async def test_await_args_list_order(self): 574 | async_mock = AsyncMock() 575 | mock2 = async_mock(2) 576 | mock1 = async_mock(1) 577 | await mock1 578 | await mock2 579 | async_mock.assert_has_awaits([call(1), call(2)]) 580 | self.assertEqual(async_mock.await_args_list, [call(1), call(2)]) 581 | self.assertEqual(async_mock.call_args_list, [call(2), call(1)]) 582 | 583 | 584 | class AsyncMagicMethods(unittest.TestCase): 585 | def test_async_magic_methods_return_async_mocks(self): 586 | m_mock = MagicMock() 587 | self.assertIsInstance(m_mock.__aenter__, AsyncMock) 588 | self.assertIsInstance(m_mock.__aexit__, AsyncMock) 589 | self.assertIsInstance(m_mock.__anext__, AsyncMock) 590 | # __aiter__ is actually a synchronous object 591 | # so should return a MagicMock 592 | self.assertIsInstance(m_mock.__aiter__, MagicMock) 593 | 594 | def test_sync_magic_methods_return_magic_mocks(self): 595 | a_mock = AsyncMock() 596 | self.assertIsInstance(a_mock.__enter__, MagicMock) 597 | self.assertIsInstance(a_mock.__exit__, MagicMock) 598 | self.assertIsInstance(a_mock.__next__, MagicMock) 599 | self.assertIsInstance(a_mock.__len__, MagicMock) 600 | 601 | def test_magicmock_has_async_magic_methods(self): 602 | m_mock = MagicMock() 603 | self.assertTrue(hasattr(m_mock, "__aenter__")) 604 | self.assertTrue(hasattr(m_mock, "__aexit__")) 605 | self.assertTrue(hasattr(m_mock, "__anext__")) 606 | 607 | def test_asyncmock_has_sync_magic_methods(self): 608 | a_mock = AsyncMock() 609 | self.assertTrue(hasattr(a_mock, "__enter__")) 610 | self.assertTrue(hasattr(a_mock, "__exit__")) 611 | self.assertTrue(hasattr(a_mock, "__next__")) 612 | self.assertTrue(hasattr(a_mock, "__len__")) 613 | 614 | def test_magic_methods_are_async_functions(self): 615 | m_mock = MagicMock() 616 | self.assertIsInstance(m_mock.__aenter__, AsyncMock) 617 | self.assertIsInstance(m_mock.__aexit__, AsyncMock) 618 | # AsyncMocks are also coroutine functions 619 | self.assertTrue(iscoroutinefunction(m_mock.__aenter__)) 620 | self.assertTrue(iscoroutinefunction(m_mock.__aexit__)) 621 | 622 | class AsyncContextManagerTest(unittest.TestCase): 623 | 624 | class WithAsyncContextManager: 625 | async def __aenter__(self, *args, **kwargs): pass 626 | 627 | async def __aexit__(self, *args, **kwargs): pass 628 | 629 | class WithSyncContextManager: 630 | def __enter__(self, *args, **kwargs): pass 631 | 632 | def __exit__(self, *args, **kwargs): pass 633 | 634 | class ProductionCode: 635 | # Example real-world(ish) code 636 | def __init__(self): 637 | self.session = None 638 | 639 | async def main(self): 640 | async with self.session.post('https://python.org') as response: 641 | val = await response.json() 642 | return val 643 | 644 | def test_set_return_value_of_aenter(self): 645 | def inner_test(mock_type): 646 | pc = self.ProductionCode() 647 | pc.session = MagicMock(name='sessionmock') 648 | cm = mock_type(name='magic_cm') 649 | response = AsyncMock(name='response') 650 | response.json = AsyncMock(return_value={'json': 123}) 651 | cm.__aenter__.return_value = response 652 | pc.session.post.return_value = cm 653 | result = run(pc.main()) 654 | self.assertEqual(result, {'json': 123}) 655 | 656 | for mock_type in [AsyncMock, MagicMock]: 657 | with self.subTest(f"test set return value of aenter with {mock_type}"): 658 | inner_test(mock_type) 659 | 660 | def test_mock_supports_async_context_manager(self): 661 | 662 | def inner_test(mock_type): 663 | called = False 664 | cm = self.WithAsyncContextManager() 665 | cm_mock = mock_type(cm) 666 | 667 | async def use_context_manager(): 668 | nonlocal called 669 | async with cm_mock as result: 670 | called = True 671 | return result 672 | 673 | cm_result = run(use_context_manager()) 674 | self.assertTrue(called) 675 | self.assertTrue(cm_mock.__aenter__.called) 676 | self.assertTrue(cm_mock.__aexit__.called) 677 | cm_mock.__aenter__.assert_awaited() 678 | cm_mock.__aexit__.assert_awaited() 679 | # We mock __aenter__ so it does not return self 680 | self.assertIsNot(cm_mock, cm_result) 681 | 682 | for mock_type in [AsyncMock, MagicMock]: 683 | with self.subTest(f"test context manager magics with {mock_type}"): 684 | inner_test(mock_type) 685 | 686 | def test_mock_customize_async_context_manager(self): 687 | instance = self.WithAsyncContextManager() 688 | mock_instance = MagicMock(instance) 689 | 690 | expected_result = object() 691 | mock_instance.__aenter__.return_value = expected_result 692 | 693 | async def use_context_manager(): 694 | async with mock_instance as result: 695 | return result 696 | 697 | self.assertIs(run(use_context_manager()), expected_result) 698 | 699 | def test_mock_customize_async_context_manager_with_coroutine(self): 700 | enter_called = False 701 | exit_called = False 702 | 703 | async def enter_coroutine(*args): 704 | nonlocal enter_called 705 | enter_called = True 706 | 707 | async def exit_coroutine(*args): 708 | nonlocal exit_called 709 | exit_called = True 710 | 711 | instance = self.WithAsyncContextManager() 712 | mock_instance = MagicMock(instance) 713 | 714 | mock_instance.__aenter__ = enter_coroutine 715 | mock_instance.__aexit__ = exit_coroutine 716 | 717 | async def use_context_manager(): 718 | async with mock_instance: 719 | pass 720 | 721 | run(use_context_manager()) 722 | self.assertTrue(enter_called) 723 | self.assertTrue(exit_called) 724 | 725 | def test_context_manager_raise_exception_by_default(self): 726 | async def raise_in(context_manager): 727 | async with context_manager: 728 | raise TypeError() 729 | 730 | instance = self.WithAsyncContextManager() 731 | mock_instance = MagicMock(instance) 732 | with self.assertRaises(TypeError): 733 | run(raise_in(mock_instance)) 734 | 735 | 736 | class AsyncIteratorTest(unittest.TestCase): 737 | class WithAsyncIterator(object): 738 | def __init__(self): 739 | self.items = ["foo", "NormalFoo", "baz"] 740 | 741 | def __aiter__(self): pass 742 | 743 | async def __anext__(self): pass 744 | 745 | def test_aiter_set_return_value(self): 746 | mock_iter = AsyncMock(name="tester") 747 | mock_iter.__aiter__.return_value = [1, 2, 3] 748 | async def main(): 749 | return [i async for i in mock_iter] 750 | result = run(main()) 751 | self.assertEqual(result, [1, 2, 3]) 752 | 753 | def test_mock_aiter_and_anext_asyncmock(self): 754 | def inner_test(mock_type): 755 | instance = self.WithAsyncIterator() 756 | mock_instance = mock_type(instance) 757 | # Check that the mock and the real thing bahave the same 758 | # __aiter__ is not actually async, so not a coroutinefunction 759 | self.assertFalse(iscoroutinefunction(instance.__aiter__)) 760 | self.assertFalse(iscoroutinefunction(mock_instance.__aiter__)) 761 | # __anext__ is async 762 | self.assertTrue(iscoroutinefunction(instance.__anext__)) 763 | self.assertTrue(iscoroutinefunction(mock_instance.__anext__)) 764 | 765 | for mock_type in [AsyncMock, MagicMock]: 766 | with self.subTest(f"test aiter and anext corourtine with {mock_type}"): 767 | inner_test(mock_type) 768 | 769 | 770 | def test_mock_async_for(self): 771 | async def iterate(iterator): 772 | accumulator = [] 773 | async for item in iterator: 774 | accumulator.append(item) 775 | 776 | return accumulator 777 | 778 | expected = ["FOO", "BAR", "BAZ"] 779 | def test_default(mock_type): 780 | mock_instance = mock_type(self.WithAsyncIterator()) 781 | self.assertEqual(run(iterate(mock_instance)), []) 782 | 783 | 784 | def test_set_return_value(mock_type): 785 | mock_instance = mock_type(self.WithAsyncIterator()) 786 | mock_instance.__aiter__.return_value = expected[:] 787 | self.assertEqual(run(iterate(mock_instance)), expected) 788 | 789 | def test_set_return_value_iter(mock_type): 790 | mock_instance = mock_type(self.WithAsyncIterator()) 791 | mock_instance.__aiter__.return_value = iter(expected[:]) 792 | self.assertEqual(run(iterate(mock_instance)), expected) 793 | 794 | for mock_type in [AsyncMock, MagicMock]: 795 | with self.subTest(f"default value with {mock_type}"): 796 | test_default(mock_type) 797 | 798 | with self.subTest(f"set return_value with {mock_type}"): 799 | test_set_return_value(mock_type) 800 | 801 | with self.subTest(f"set return_value iterator with {mock_type}"): 802 | test_set_return_value_iter(mock_type) 803 | 804 | 805 | class AsyncMockAssert(unittest.TestCase): 806 | def setUp(self): 807 | self.mock = AsyncMock() 808 | 809 | async def _runnable_test(self, *args, **kwargs): 810 | await self.mock(*args, **kwargs) 811 | 812 | async def _await_coroutine(self, coroutine): 813 | return await coroutine 814 | 815 | def test_assert_called_but_not_awaited(self): 816 | mock = AsyncMock(AsyncClass) 817 | with assertNeverAwaited(self): 818 | mock.async_method() 819 | self.assertTrue(iscoroutinefunction(mock.async_method)) 820 | mock.async_method.assert_called() 821 | mock.async_method.assert_called_once() 822 | mock.async_method.assert_called_once_with() 823 | with self.assertRaises(AssertionError): 824 | mock.assert_awaited() 825 | with self.assertRaises(AssertionError): 826 | mock.async_method.assert_awaited() 827 | 828 | def test_assert_called_then_awaited(self): 829 | mock = AsyncMock(AsyncClass) 830 | mock_coroutine = mock.async_method() 831 | mock.async_method.assert_called() 832 | mock.async_method.assert_called_once() 833 | mock.async_method.assert_called_once_with() 834 | with self.assertRaises(AssertionError): 835 | mock.async_method.assert_awaited() 836 | 837 | run(self._await_coroutine(mock_coroutine)) 838 | # Assert we haven't re-called the function 839 | mock.async_method.assert_called_once() 840 | mock.async_method.assert_awaited() 841 | mock.async_method.assert_awaited_once() 842 | mock.async_method.assert_awaited_once_with() 843 | 844 | def test_assert_called_and_awaited_at_same_time(self): 845 | with self.assertRaises(AssertionError): 846 | self.mock.assert_awaited() 847 | 848 | with self.assertRaises(AssertionError): 849 | self.mock.assert_called() 850 | 851 | run(self._runnable_test()) 852 | self.mock.assert_called_once() 853 | self.mock.assert_awaited_once() 854 | 855 | def test_assert_called_twice_and_awaited_once(self): 856 | mock = AsyncMock(AsyncClass) 857 | coroutine = mock.async_method() 858 | # The first call will be awaited so no warning there 859 | # But this call will never get awaited, so it will warn here 860 | with assertNeverAwaited(self): 861 | mock.async_method() 862 | with self.assertRaises(AssertionError): 863 | mock.async_method.assert_awaited() 864 | mock.async_method.assert_called() 865 | run(self._await_coroutine(coroutine)) 866 | mock.async_method.assert_awaited() 867 | mock.async_method.assert_awaited_once() 868 | 869 | def test_assert_called_once_and_awaited_twice(self): 870 | mock = AsyncMock(AsyncClass) 871 | coroutine = mock.async_method() 872 | mock.async_method.assert_called_once() 873 | run(self._await_coroutine(coroutine)) 874 | with self.assertRaises(RuntimeError): 875 | # Cannot reuse already awaited coroutine 876 | run(self._await_coroutine(coroutine)) 877 | mock.async_method.assert_awaited() 878 | 879 | def test_assert_awaited_but_not_called(self): 880 | with self.assertRaises(AssertionError): 881 | self.mock.assert_awaited() 882 | with self.assertRaises(AssertionError): 883 | self.mock.assert_called() 884 | with self.assertRaises(TypeError): 885 | # You cannot await an AsyncMock, it must be a coroutine 886 | run(self._await_coroutine(self.mock)) 887 | 888 | with self.assertRaises(AssertionError): 889 | self.mock.assert_awaited() 890 | with self.assertRaises(AssertionError): 891 | self.mock.assert_called() 892 | 893 | def test_assert_has_calls_not_awaits(self): 894 | kalls = [call('foo')] 895 | with assertNeverAwaited(self): 896 | self.mock('foo') 897 | self.mock.assert_has_calls(kalls) 898 | with self.assertRaises(AssertionError): 899 | self.mock.assert_has_awaits(kalls) 900 | 901 | def test_assert_has_mock_calls_on_async_mock_no_spec(self): 902 | with assertNeverAwaited(self): 903 | self.mock() 904 | kalls_empty = [('', (), {})] 905 | self.assertEqual(self.mock.mock_calls, kalls_empty) 906 | 907 | with assertNeverAwaited(self): 908 | self.mock('foo') 909 | with assertNeverAwaited(self): 910 | self.mock('baz') 911 | mock_kalls = ([call(), call('foo'), call('baz')]) 912 | self.assertEqual(self.mock.mock_calls, mock_kalls) 913 | 914 | def test_assert_has_mock_calls_on_async_mock_with_spec(self): 915 | a_class_mock = AsyncMock(AsyncClass) 916 | with assertNeverAwaited(self): 917 | a_class_mock.async_method() 918 | kalls_empty = [('', (), {})] 919 | self.assertEqual(a_class_mock.async_method.mock_calls, kalls_empty) 920 | self.assertEqual(a_class_mock.mock_calls, [call.async_method()]) 921 | 922 | with assertNeverAwaited(self): 923 | a_class_mock.async_method(1, 2, 3, a=4, b=5) 924 | method_kalls = [call(), call(1, 2, 3, a=4, b=5)] 925 | mock_kalls = [call.async_method(), call.async_method(1, 2, 3, a=4, b=5)] 926 | self.assertEqual(a_class_mock.async_method.mock_calls, method_kalls) 927 | self.assertEqual(a_class_mock.mock_calls, mock_kalls) 928 | 929 | def test_async_method_calls_recorded(self): 930 | with assertNeverAwaited(self): 931 | self.mock.something(3, fish=None) 932 | with assertNeverAwaited(self): 933 | self.mock.something_else.something(6, cake=sentinel.Cake) 934 | 935 | self.assertEqual(self.mock.method_calls, [ 936 | ("something", (3,), {'fish': None}), 937 | ("something_else.something", (6,), {'cake': sentinel.Cake}) 938 | ], 939 | "method calls not recorded correctly") 940 | self.assertEqual(self.mock.something_else.method_calls, 941 | [("something", (6,), {'cake': sentinel.Cake})], 942 | "method calls not recorded correctly") 943 | 944 | def test_async_arg_lists(self): 945 | def assert_attrs(mock): 946 | names = ('call_args_list', 'method_calls', 'mock_calls') 947 | for name in names: 948 | attr = getattr(mock, name) 949 | self.assertIsInstance(attr, _CallList) 950 | self.assertIsInstance(attr, list) 951 | self.assertEqual(attr, []) 952 | 953 | assert_attrs(self.mock) 954 | with assertNeverAwaited(self): 955 | self.mock() 956 | with assertNeverAwaited(self): 957 | self.mock(1, 2) 958 | with assertNeverAwaited(self): 959 | self.mock(a=3) 960 | 961 | self.mock.reset_mock() 962 | assert_attrs(self.mock) 963 | 964 | a_mock = AsyncMock(AsyncClass) 965 | with assertNeverAwaited(self): 966 | a_mock.async_method() 967 | with assertNeverAwaited(self): 968 | a_mock.async_method(1, a=3) 969 | 970 | a_mock.reset_mock() 971 | assert_attrs(a_mock) 972 | 973 | def test_assert_awaited(self): 974 | with self.assertRaises(AssertionError): 975 | self.mock.assert_awaited() 976 | 977 | run(self._runnable_test()) 978 | self.mock.assert_awaited() 979 | 980 | def test_assert_awaited_once(self): 981 | with self.assertRaises(AssertionError): 982 | self.mock.assert_awaited_once() 983 | 984 | run(self._runnable_test()) 985 | self.mock.assert_awaited_once() 986 | 987 | run(self._runnable_test()) 988 | with self.assertRaises(AssertionError): 989 | self.mock.assert_awaited_once() 990 | 991 | def test_assert_awaited_with(self): 992 | msg = 'Not awaited' 993 | with self.assertRaisesRegex(AssertionError, msg): 994 | self.mock.assert_awaited_with('foo') 995 | 996 | run(self._runnable_test()) 997 | msg = 'expected await not found' 998 | with self.assertRaisesRegex(AssertionError, msg): 999 | self.mock.assert_awaited_with('foo') 1000 | 1001 | run(self._runnable_test('foo')) 1002 | self.mock.assert_awaited_with('foo') 1003 | 1004 | run(self._runnable_test('SomethingElse')) 1005 | with self.assertRaises(AssertionError): 1006 | self.mock.assert_awaited_with('foo') 1007 | 1008 | def test_assert_awaited_once_with(self): 1009 | with self.assertRaises(AssertionError): 1010 | self.mock.assert_awaited_once_with('foo') 1011 | 1012 | run(self._runnable_test('foo')) 1013 | self.mock.assert_awaited_once_with('foo') 1014 | 1015 | run(self._runnable_test('foo')) 1016 | with self.assertRaises(AssertionError): 1017 | self.mock.assert_awaited_once_with('foo') 1018 | 1019 | def test_assert_any_wait(self): 1020 | with self.assertRaises(AssertionError): 1021 | self.mock.assert_any_await('foo') 1022 | 1023 | run(self._runnable_test('baz')) 1024 | with self.assertRaises(AssertionError): 1025 | self.mock.assert_any_await('foo') 1026 | 1027 | run(self._runnable_test('foo')) 1028 | self.mock.assert_any_await('foo') 1029 | 1030 | run(self._runnable_test('SomethingElse')) 1031 | self.mock.assert_any_await('foo') 1032 | 1033 | def test_assert_has_awaits_no_order(self): 1034 | calls = [call('foo'), call('baz')] 1035 | 1036 | with self.assertRaises(AssertionError) as cm: 1037 | self.mock.assert_has_awaits(calls) 1038 | self.assertEqual(len(cm.exception.args), 1) 1039 | 1040 | run(self._runnable_test('foo')) 1041 | with self.assertRaises(AssertionError): 1042 | self.mock.assert_has_awaits(calls) 1043 | 1044 | run(self._runnable_test('foo')) 1045 | with self.assertRaises(AssertionError): 1046 | self.mock.assert_has_awaits(calls) 1047 | 1048 | run(self._runnable_test('baz')) 1049 | self.mock.assert_has_awaits(calls) 1050 | 1051 | run(self._runnable_test('SomethingElse')) 1052 | self.mock.assert_has_awaits(calls) 1053 | 1054 | def test_awaits_asserts_with_any(self): 1055 | class Foo: 1056 | def __eq__(self, other): pass 1057 | 1058 | run(self._runnable_test(Foo(), 1)) 1059 | 1060 | self.mock.assert_has_awaits([call(ANY, 1)]) 1061 | self.mock.assert_awaited_with(ANY, 1) 1062 | self.mock.assert_any_await(ANY, 1) 1063 | 1064 | def test_awaits_asserts_with_spec_and_any(self): 1065 | class Foo: 1066 | def __eq__(self, other): pass 1067 | 1068 | mock_with_spec = AsyncMock(spec=Foo) 1069 | 1070 | async def _custom_mock_runnable_test(*args): 1071 | await mock_with_spec(*args) 1072 | 1073 | run(_custom_mock_runnable_test(Foo(), 1)) 1074 | mock_with_spec.assert_has_awaits([call(ANY, 1)]) 1075 | mock_with_spec.assert_awaited_with(ANY, 1) 1076 | mock_with_spec.assert_any_await(ANY, 1) 1077 | 1078 | def test_assert_has_awaits_ordered(self): 1079 | calls = [call('foo'), call('baz')] 1080 | with self.assertRaises(AssertionError): 1081 | self.mock.assert_has_awaits(calls, any_order=True) 1082 | 1083 | run(self._runnable_test('baz')) 1084 | with self.assertRaises(AssertionError): 1085 | self.mock.assert_has_awaits(calls, any_order=True) 1086 | 1087 | run(self._runnable_test('bamf')) 1088 | with self.assertRaises(AssertionError): 1089 | self.mock.assert_has_awaits(calls, any_order=True) 1090 | 1091 | run(self._runnable_test('foo')) 1092 | self.mock.assert_has_awaits(calls, any_order=True) 1093 | 1094 | run(self._runnable_test('qux')) 1095 | self.mock.assert_has_awaits(calls, any_order=True) 1096 | 1097 | def test_assert_not_awaited(self): 1098 | self.mock.assert_not_awaited() 1099 | 1100 | run(self._runnable_test()) 1101 | with self.assertRaises(AssertionError): 1102 | self.mock.assert_not_awaited() 1103 | 1104 | def test_assert_has_awaits_not_matching_spec_error(self): 1105 | async def f(x=None): pass 1106 | 1107 | self.mock = AsyncMock(spec=f) 1108 | run(self._runnable_test(1)) 1109 | 1110 | with self.assertRaisesRegex( 1111 | AssertionError, 1112 | '^{}$'.format( 1113 | re.escape('Awaits not found.\n' 1114 | 'Expected: [call()]\n' 1115 | 'Actual: [call(1)]'))) as cm: 1116 | self.mock.assert_has_awaits([call()]) 1117 | self.assertIsNone(cm.exception.__cause__) 1118 | 1119 | with self.assertRaisesRegex( 1120 | AssertionError, 1121 | '^{}$'.format( 1122 | re.escape( 1123 | 'Error processing expected awaits.\n' 1124 | "Errors: [None, TypeError('too many positional " 1125 | "arguments')]\n" 1126 | 'Expected: [call(), call(1, 2)]\n' 1127 | 'Actual: [call(1)]').replace( 1128 | "arguments\\'", "arguments\\',?") 1129 | )) as cm: 1130 | self.mock.assert_has_awaits([call(), call(1, 2)]) 1131 | self.assertIsInstance(cm.exception.__cause__, TypeError) 1132 | 1133 | 1134 | if __name__ == '__main__': 1135 | unittest.main() 1136 | -------------------------------------------------------------------------------- /mock/tests/testcallable.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2007-2012 Michael Foord & the mock team 2 | # E-mail: fuzzyman AT voidspace DOT org DOT uk 3 | # http://www.voidspace.org.uk/python/mock/ 4 | 5 | import unittest 6 | from mock.tests.support import is_instance, X, SomeClass 7 | 8 | from mock import ( 9 | Mock, MagicMock, NonCallableMagicMock, 10 | NonCallableMock, patch, create_autospec, 11 | ) 12 | from mock.mock import CallableMixin 13 | 14 | 15 | class TestCallable(unittest.TestCase): 16 | 17 | def assertNotCallable(self, mock): 18 | self.assertTrue(is_instance(mock, NonCallableMagicMock)) 19 | self.assertFalse(is_instance(mock, CallableMixin)) 20 | 21 | 22 | def test_non_callable(self): 23 | for mock in NonCallableMagicMock(), NonCallableMock(): 24 | self.assertRaises(TypeError, mock) 25 | self.assertFalse(hasattr(mock, '__call__')) 26 | self.assertIn(mock.__class__.__name__, repr(mock)) 27 | 28 | 29 | def test_hierarchy(self): 30 | self.assertTrue(issubclass(MagicMock, Mock)) 31 | self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock)) 32 | 33 | 34 | def test_attributes(self): 35 | one = NonCallableMock() 36 | self.assertTrue(issubclass(type(one.one), Mock)) 37 | 38 | two = NonCallableMagicMock() 39 | self.assertTrue(issubclass(type(two.two), MagicMock)) 40 | 41 | 42 | def test_subclasses(self): 43 | class MockSub(Mock): 44 | pass 45 | 46 | one = MockSub() 47 | self.assertTrue(issubclass(type(one.one), MockSub)) 48 | 49 | class MagicSub(MagicMock): 50 | pass 51 | 52 | two = MagicSub() 53 | self.assertTrue(issubclass(type(two.two), MagicSub)) 54 | 55 | 56 | def test_patch_spec(self): 57 | patcher = patch('%s.X' % __name__, spec=True) 58 | mock = patcher.start() 59 | self.addCleanup(patcher.stop) 60 | 61 | instance = mock() 62 | mock.assert_called_once_with() 63 | 64 | self.assertNotCallable(instance) 65 | self.assertRaises(TypeError, instance) 66 | 67 | 68 | def test_patch_spec_set(self): 69 | patcher = patch('%s.X' % __name__, spec_set=True) 70 | mock = patcher.start() 71 | self.addCleanup(patcher.stop) 72 | 73 | instance = mock() 74 | mock.assert_called_once_with() 75 | 76 | self.assertNotCallable(instance) 77 | self.assertRaises(TypeError, instance) 78 | 79 | 80 | def test_patch_spec_instance(self): 81 | patcher = patch('%s.X' % __name__, spec=X()) 82 | mock = patcher.start() 83 | self.addCleanup(patcher.stop) 84 | 85 | self.assertNotCallable(mock) 86 | self.assertRaises(TypeError, mock) 87 | 88 | 89 | def test_patch_spec_set_instance(self): 90 | patcher = patch('%s.X' % __name__, spec_set=X()) 91 | mock = patcher.start() 92 | self.addCleanup(patcher.stop) 93 | 94 | self.assertNotCallable(mock) 95 | self.assertRaises(TypeError, mock) 96 | 97 | 98 | def test_patch_spec_callable_class(self): 99 | class CallableX(X): 100 | def __call__(self): pass 101 | 102 | class Sub(CallableX): 103 | pass 104 | 105 | class Multi(SomeClass, Sub): 106 | pass 107 | 108 | for arg in 'spec', 'spec_set': 109 | for Klass in CallableX, Sub, Multi: 110 | with patch('%s.X' % __name__, **{arg: Klass}) as mock: 111 | instance = mock() 112 | mock.assert_called_once_with() 113 | 114 | self.assertTrue(is_instance(instance, MagicMock)) 115 | # inherited spec 116 | self.assertRaises(AttributeError, getattr, instance, 117 | 'foobarbaz') 118 | 119 | result = instance() 120 | # instance is callable, result has no spec 121 | instance.assert_called_once_with() 122 | 123 | result(3, 2, 1) 124 | result.assert_called_once_with(3, 2, 1) 125 | result.foo(3, 2, 1) 126 | result.foo.assert_called_once_with(3, 2, 1) 127 | 128 | 129 | def test_create_autospec(self): 130 | mock = create_autospec(X) 131 | instance = mock() 132 | self.assertRaises(TypeError, instance) 133 | 134 | mock = create_autospec(X()) 135 | self.assertRaises(TypeError, mock) 136 | 137 | 138 | def test_create_autospec_instance(self): 139 | mock = create_autospec(SomeClass, instance=True) 140 | 141 | self.assertRaises(TypeError, mock) 142 | mock.wibble() 143 | mock.wibble.assert_called_once_with() 144 | 145 | self.assertRaises(TypeError, mock.wibble, 'some', 'args') 146 | 147 | 148 | if __name__ == "__main__": 149 | unittest.main() 150 | -------------------------------------------------------------------------------- /mock/tests/testhelpers.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import time 3 | import types 4 | import unittest 5 | 6 | from mock import ( 7 | call, create_autospec, MagicMock, 8 | Mock, ANY, patch, PropertyMock 9 | ) 10 | from mock.mock import _Call, _CallList, _callable 11 | from mock import IS_PYPY 12 | 13 | try: 14 | from dataclasses import dataclass, field, InitVar 15 | except ImportError: 16 | pass 17 | 18 | from datetime import datetime 19 | from functools import partial 20 | from typing import ClassVar 21 | 22 | import pytest 23 | import sys 24 | 25 | 26 | class SomeClass(object): 27 | def one(self, a, b): pass 28 | def two(self): pass 29 | def three(self, a=None): pass 30 | 31 | 32 | class AnyTest(unittest.TestCase): 33 | 34 | def test_any(self): 35 | self.assertEqual(ANY, object()) 36 | 37 | mock = Mock() 38 | mock(ANY) 39 | mock.assert_called_with(ANY) 40 | 41 | mock = Mock() 42 | mock(foo=ANY) 43 | mock.assert_called_with(foo=ANY) 44 | 45 | def test_repr(self): 46 | self.assertEqual(repr(ANY), '') 47 | self.assertEqual(str(ANY), '') 48 | 49 | 50 | def test_any_and_datetime(self): 51 | mock = Mock() 52 | mock(datetime.now(), foo=datetime.now()) 53 | 54 | mock.assert_called_with(ANY, foo=ANY) 55 | 56 | 57 | def test_any_mock_calls_comparison_order(self): 58 | mock = Mock() 59 | class Foo(object): 60 | def __eq__(self, other): pass 61 | def __ne__(self, other): pass 62 | 63 | for d in datetime.now(), Foo(): 64 | mock.reset_mock() 65 | 66 | mock(d, foo=d, bar=d) 67 | mock.method(d, zinga=d, alpha=d) 68 | mock().method(a1=d, z99=d) 69 | 70 | expected = [ 71 | call(ANY, foo=ANY, bar=ANY), 72 | call.method(ANY, zinga=ANY, alpha=ANY), 73 | call(), call().method(a1=ANY, z99=ANY) 74 | ] 75 | self.assertEqual(expected, mock.mock_calls) 76 | self.assertEqual(mock.mock_calls, expected) 77 | 78 | def test_any_no_spec(self): 79 | # This is a regression test for bpo-37555 80 | class Foo: 81 | def __eq__(self, other): pass 82 | 83 | mock = Mock() 84 | mock(Foo(), 1) 85 | mock.assert_has_calls([call(ANY, 1)]) 86 | mock.assert_called_with(ANY, 1) 87 | mock.assert_any_call(ANY, 1) 88 | 89 | def test_any_and_spec_set(self): 90 | # This is a regression test for bpo-37555 91 | class Foo: 92 | def __eq__(self, other): pass 93 | 94 | mock = Mock(spec=Foo) 95 | 96 | mock(Foo(), 1) 97 | mock.assert_has_calls([call(ANY, 1)]) 98 | mock.assert_called_with(ANY, 1) 99 | mock.assert_any_call(ANY, 1) 100 | 101 | class CallTest(unittest.TestCase): 102 | 103 | def test_call_with_call(self): 104 | kall = _Call() 105 | self.assertEqual(kall, _Call()) 106 | self.assertEqual(kall, _Call(('',))) 107 | self.assertEqual(kall, _Call(((),))) 108 | self.assertEqual(kall, _Call(({},))) 109 | self.assertEqual(kall, _Call(('', ()))) 110 | self.assertEqual(kall, _Call(('', {}))) 111 | self.assertEqual(kall, _Call(('', (), {}))) 112 | self.assertEqual(kall, _Call(('foo',))) 113 | self.assertEqual(kall, _Call(('bar', ()))) 114 | self.assertEqual(kall, _Call(('baz', {}))) 115 | self.assertEqual(kall, _Call(('spam', (), {}))) 116 | 117 | kall = _Call(((1, 2, 3),)) 118 | self.assertEqual(kall, _Call(((1, 2, 3),))) 119 | self.assertEqual(kall, _Call(('', (1, 2, 3)))) 120 | self.assertEqual(kall, _Call(((1, 2, 3), {}))) 121 | self.assertEqual(kall, _Call(('', (1, 2, 3), {}))) 122 | 123 | kall = _Call(((1, 2, 4),)) 124 | self.assertNotEqual(kall, _Call(('', (1, 2, 3)))) 125 | self.assertNotEqual(kall, _Call(('', (1, 2, 3), {}))) 126 | 127 | kall = _Call(('foo', (1, 2, 4),)) 128 | self.assertNotEqual(kall, _Call(('', (1, 2, 4)))) 129 | self.assertNotEqual(kall, _Call(('', (1, 2, 4), {}))) 130 | self.assertNotEqual(kall, _Call(('bar', (1, 2, 4)))) 131 | self.assertNotEqual(kall, _Call(('bar', (1, 2, 4), {}))) 132 | 133 | kall = _Call(({'a': 3},)) 134 | self.assertEqual(kall, _Call(('', (), {'a': 3}))) 135 | self.assertEqual(kall, _Call(('', {'a': 3}))) 136 | self.assertEqual(kall, _Call(((), {'a': 3}))) 137 | self.assertEqual(kall, _Call(({'a': 3},))) 138 | 139 | 140 | def test_empty__Call(self): 141 | args = _Call() 142 | 143 | self.assertEqual(args, ()) 144 | self.assertEqual(args, ('foo',)) 145 | self.assertEqual(args, ((),)) 146 | self.assertEqual(args, ('foo', ())) 147 | self.assertEqual(args, ('foo',(), {})) 148 | self.assertEqual(args, ('foo', {})) 149 | self.assertEqual(args, ({},)) 150 | 151 | 152 | def test_named_empty_call(self): 153 | args = _Call(('foo', (), {})) 154 | 155 | self.assertEqual(args, ('foo',)) 156 | self.assertEqual(args, ('foo', ())) 157 | self.assertEqual(args, ('foo',(), {})) 158 | self.assertEqual(args, ('foo', {})) 159 | 160 | self.assertNotEqual(args, ((),)) 161 | self.assertNotEqual(args, ()) 162 | self.assertNotEqual(args, ({},)) 163 | self.assertNotEqual(args, ('bar',)) 164 | self.assertNotEqual(args, ('bar', ())) 165 | self.assertNotEqual(args, ('bar', {})) 166 | 167 | 168 | def test_call_with_args(self): 169 | args = _Call(((1, 2, 3), {})) 170 | 171 | self.assertEqual(args, ((1, 2, 3),)) 172 | self.assertEqual(args, ('foo', (1, 2, 3))) 173 | self.assertEqual(args, ('foo', (1, 2, 3), {})) 174 | self.assertEqual(args, ((1, 2, 3), {})) 175 | self.assertEqual(args.args, (1, 2, 3)) 176 | self.assertEqual(args.kwargs, {}) 177 | 178 | 179 | def test_named_call_with_args(self): 180 | args = _Call(('foo', (1, 2, 3), {})) 181 | 182 | self.assertEqual(args, ('foo', (1, 2, 3))) 183 | self.assertEqual(args, ('foo', (1, 2, 3), {})) 184 | self.assertEqual(args.args, (1, 2, 3)) 185 | self.assertEqual(args.kwargs, {}) 186 | 187 | self.assertNotEqual(args, ((1, 2, 3),)) 188 | self.assertNotEqual(args, ((1, 2, 3), {})) 189 | 190 | 191 | def test_call_with_kwargs(self): 192 | args = _Call(((), dict(a=3, b=4))) 193 | 194 | self.assertEqual(args, (dict(a=3, b=4),)) 195 | self.assertEqual(args, ('foo', dict(a=3, b=4))) 196 | self.assertEqual(args, ('foo', (), dict(a=3, b=4))) 197 | self.assertEqual(args, ((), dict(a=3, b=4))) 198 | self.assertEqual(args.args, ()) 199 | self.assertEqual(args.kwargs, dict(a=3, b=4)) 200 | 201 | 202 | def test_named_call_with_kwargs(self): 203 | args = _Call(('foo', (), dict(a=3, b=4))) 204 | 205 | self.assertEqual(args, ('foo', dict(a=3, b=4))) 206 | self.assertEqual(args, ('foo', (), dict(a=3, b=4))) 207 | self.assertEqual(args.args, ()) 208 | self.assertEqual(args.kwargs, dict(a=3, b=4)) 209 | 210 | self.assertNotEqual(args, (dict(a=3, b=4),)) 211 | self.assertNotEqual(args, ((), dict(a=3, b=4))) 212 | 213 | 214 | def test_call_with_args_call_empty_name(self): 215 | args = _Call(((1, 2, 3), {})) 216 | 217 | self.assertEqual(args, call(1, 2, 3)) 218 | self.assertEqual(call(1, 2, 3), args) 219 | self.assertIn(call(1, 2, 3), [args]) 220 | 221 | 222 | def test_call_ne(self): 223 | self.assertNotEqual(_Call(((1, 2, 3),)), call(1, 2)) 224 | self.assertFalse(_Call(((1, 2, 3),)) != call(1, 2, 3)) 225 | self.assertTrue(_Call(((1, 2), {})) != call(1, 2, 3)) 226 | 227 | 228 | def test_call_non_tuples(self): 229 | kall = _Call(((1, 2, 3),)) 230 | for value in 1, None, self, int: 231 | self.assertNotEqual(kall, value) 232 | self.assertFalse(kall == value) 233 | 234 | 235 | def test_repr(self): 236 | self.assertEqual(repr(_Call()), 'call()') 237 | self.assertEqual(repr(_Call(('foo',))), 'call.foo()') 238 | 239 | self.assertEqual(repr(_Call(((1, 2, 3), {'a': 'b'}))), 240 | "call(1, 2, 3, a='b')") 241 | self.assertEqual(repr(_Call(('bar', (1, 2, 3), {'a': 'b'}))), 242 | "call.bar(1, 2, 3, a='b')") 243 | 244 | self.assertEqual(repr(call), 'call') 245 | self.assertEqual(str(call), 'call') 246 | 247 | self.assertEqual(repr(call()), 'call()') 248 | self.assertEqual(repr(call(1)), 'call(1)') 249 | self.assertEqual(repr(call(zz='thing')), "call(zz='thing')") 250 | 251 | self.assertEqual(repr(call().foo), 'call().foo') 252 | self.assertEqual(repr(call(1).foo.bar(a=3).bing), 253 | 'call().foo.bar().bing') 254 | self.assertEqual( 255 | repr(call().foo(1, 2, a=3)), 256 | "call().foo(1, 2, a=3)" 257 | ) 258 | self.assertEqual(repr(call()()), "call()()") 259 | self.assertEqual(repr(call(1)(2)), "call()(2)") 260 | self.assertEqual( 261 | repr(call()().bar().baz.beep(1)), 262 | "call()().bar().baz.beep(1)" 263 | ) 264 | 265 | 266 | def test_call(self): 267 | self.assertEqual(call(), ('', (), {})) 268 | self.assertEqual(call('foo', 'bar', one=3, two=4), 269 | ('', ('foo', 'bar'), {'one': 3, 'two': 4})) 270 | 271 | mock = Mock() 272 | mock(1, 2, 3) 273 | mock(a=3, b=6) 274 | self.assertEqual(mock.call_args_list, 275 | [call(1, 2, 3), call(a=3, b=6)]) 276 | 277 | def test_attribute_call(self): 278 | self.assertEqual(call.foo(1), ('foo', (1,), {})) 279 | self.assertEqual(call.bar.baz(fish='eggs'), 280 | ('bar.baz', (), {'fish': 'eggs'})) 281 | 282 | mock = Mock() 283 | mock.foo(1, 2 ,3) 284 | mock.bar.baz(a=3, b=6) 285 | self.assertEqual(mock.method_calls, 286 | [call.foo(1, 2, 3), call.bar.baz(a=3, b=6)]) 287 | 288 | 289 | def test_extended_call(self): 290 | result = call(1).foo(2).bar(3, a=4) 291 | self.assertEqual(result, ('().foo().bar', (3,), dict(a=4))) 292 | 293 | mock = MagicMock() 294 | mock(1, 2, a=3, b=4) 295 | self.assertEqual(mock.call_args, call(1, 2, a=3, b=4)) 296 | self.assertNotEqual(mock.call_args, call(1, 2, 3)) 297 | 298 | self.assertEqual(mock.call_args_list, [call(1, 2, a=3, b=4)]) 299 | self.assertEqual(mock.mock_calls, [call(1, 2, a=3, b=4)]) 300 | 301 | mock = MagicMock() 302 | mock.foo(1).bar()().baz.beep(a=6) 303 | 304 | last_call = call.foo(1).bar()().baz.beep(a=6) 305 | self.assertEqual(mock.mock_calls[-1], last_call) 306 | self.assertEqual(mock.mock_calls, last_call.call_list()) 307 | 308 | 309 | def test_extended_not_equal(self): 310 | a = call(x=1).foo 311 | b = call(x=2).foo 312 | self.assertEqual(a, a) 313 | self.assertEqual(b, b) 314 | self.assertNotEqual(a, b) 315 | 316 | 317 | def test_nested_calls_not_equal(self): 318 | a = call(x=1).foo().bar 319 | b = call(x=2).foo().bar 320 | self.assertEqual(a, a) 321 | self.assertEqual(b, b) 322 | self.assertNotEqual(a, b) 323 | 324 | 325 | def test_call_list(self): 326 | mock = MagicMock() 327 | mock(1) 328 | self.assertEqual(call(1).call_list(), mock.mock_calls) 329 | 330 | mock = MagicMock() 331 | mock(1).method(2) 332 | self.assertEqual(call(1).method(2).call_list(), 333 | mock.mock_calls) 334 | 335 | mock = MagicMock() 336 | mock(1).method(2)(3) 337 | self.assertEqual(call(1).method(2)(3).call_list(), 338 | mock.mock_calls) 339 | 340 | mock = MagicMock() 341 | int(mock(1).method(2)(3).foo.bar.baz(4)(5)) 342 | kall = call(1).method(2)(3).foo.bar.baz(4)(5).__int__() 343 | self.assertEqual(kall.call_list(), mock.mock_calls) 344 | 345 | 346 | def test_call_any(self): 347 | self.assertEqual(call, ANY) 348 | 349 | m = MagicMock() 350 | int(m) 351 | self.assertEqual(m.mock_calls, [ANY]) 352 | self.assertEqual([ANY], m.mock_calls) 353 | 354 | 355 | def test_two_args_call(self): 356 | args = _Call(((1, 2), {'a': 3}), two=True) 357 | self.assertEqual(len(args), 2) 358 | self.assertEqual(args[0], (1, 2)) 359 | self.assertEqual(args[1], {'a': 3}) 360 | 361 | other_args = _Call(((1, 2), {'a': 3})) 362 | self.assertEqual(args, other_args) 363 | 364 | def test_call_with_name(self): 365 | self.assertEqual(_Call((), 'foo')[0], 'foo') 366 | self.assertEqual(_Call((('bar', 'barz'),),)[0], '') 367 | self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '') 368 | 369 | def test_dunder_call(self): 370 | m = MagicMock() 371 | m().foo()['bar']() 372 | self.assertEqual( 373 | m.mock_calls, 374 | [call(), call().foo(), call().foo().__getitem__('bar'), call().foo().__getitem__()()] 375 | ) 376 | m = MagicMock() 377 | m().foo()['bar'] = 1 378 | self.assertEqual( 379 | m.mock_calls, 380 | [call(), call().foo(), call().foo().__setitem__('bar', 1)] 381 | ) 382 | m = MagicMock() 383 | iter(m().foo()) 384 | self.assertEqual( 385 | m.mock_calls, 386 | [call(), call().foo(), call().foo().__iter__()] 387 | ) 388 | 389 | 390 | class SpecSignatureTest(unittest.TestCase): 391 | 392 | def _check_someclass_mock(self, mock): 393 | self.assertRaises(AttributeError, getattr, mock, 'foo') 394 | mock.one(1, 2) 395 | mock.one.assert_called_with(1, 2) 396 | self.assertRaises(AssertionError, 397 | mock.one.assert_called_with, 3, 4) 398 | self.assertRaises(TypeError, mock.one, 1) 399 | 400 | mock.two() 401 | mock.two.assert_called_with() 402 | self.assertRaises(AssertionError, 403 | mock.two.assert_called_with, 3) 404 | self.assertRaises(TypeError, mock.two, 1) 405 | 406 | mock.three() 407 | mock.three.assert_called_with() 408 | self.assertRaises(AssertionError, 409 | mock.three.assert_called_with, 3) 410 | self.assertRaises(TypeError, mock.three, 3, 2) 411 | 412 | mock.three(1) 413 | mock.three.assert_called_with(1) 414 | 415 | mock.three(a=1) 416 | mock.three.assert_called_with(a=1) 417 | 418 | 419 | def test_basic(self): 420 | mock = create_autospec(SomeClass) 421 | self._check_someclass_mock(mock) 422 | mock = create_autospec(SomeClass()) 423 | self._check_someclass_mock(mock) 424 | 425 | 426 | def test_create_autospec_return_value(self): 427 | def f(): pass 428 | mock = create_autospec(f, return_value='foo') 429 | self.assertEqual(mock(), 'foo') 430 | 431 | class Foo(object): 432 | pass 433 | 434 | mock = create_autospec(Foo, return_value='foo') 435 | self.assertEqual(mock(), 'foo') 436 | 437 | 438 | def test_autospec_reset_mock(self): 439 | m = create_autospec(int) 440 | int(m) 441 | m.reset_mock() 442 | self.assertEqual(m.__int__.call_count, 0) 443 | 444 | 445 | def test_mocking_unbound_methods(self): 446 | class Foo(object): 447 | def foo(self, foo): pass 448 | p = patch.object(Foo, 'foo') 449 | mock_foo = p.start() 450 | Foo().foo(1) 451 | 452 | mock_foo.assert_called_with(1) 453 | 454 | 455 | def test_create_autospec_keyword_arguments(self): 456 | class Foo(object): 457 | a = 3 458 | m = create_autospec(Foo, a='3') 459 | self.assertEqual(m.a, '3') 460 | 461 | 462 | def test_create_autospec_keyword_only_arguments(self): 463 | def foo(a, *, b=None): pass 464 | 465 | m = create_autospec(foo) 466 | m(1) 467 | m.assert_called_with(1) 468 | self.assertRaises(TypeError, m, 1, 2) 469 | 470 | m(2, b=3) 471 | m.assert_called_with(2, b=3) 472 | 473 | 474 | def test_function_as_instance_attribute(self): 475 | obj = SomeClass() 476 | def f(a): pass 477 | obj.f = f 478 | 479 | mock = create_autospec(obj) 480 | mock.f('bing') 481 | mock.f.assert_called_with('bing') 482 | 483 | 484 | def test_spec_as_list(self): 485 | # because spec as a list of strings in the mock constructor means 486 | # something very different we treat a list instance as the type. 487 | mock = create_autospec([]) 488 | mock.append('foo') 489 | mock.append.assert_called_with('foo') 490 | 491 | self.assertRaises(AttributeError, getattr, mock, 'foo') 492 | 493 | class Foo(object): 494 | foo = [] 495 | 496 | mock = create_autospec(Foo) 497 | mock.foo.append(3) 498 | mock.foo.append.assert_called_with(3) 499 | self.assertRaises(AttributeError, getattr, mock.foo, 'foo') 500 | 501 | 502 | def test_attributes(self): 503 | class Sub(SomeClass): 504 | attr = SomeClass() 505 | 506 | sub_mock = create_autospec(Sub) 507 | 508 | for mock in (sub_mock, sub_mock.attr): 509 | self._check_someclass_mock(mock) 510 | 511 | 512 | def test_spec_has_descriptor_returning_function(self): 513 | 514 | class CrazyDescriptor(object): 515 | 516 | def __get__(self, obj, type_): 517 | if obj is None: 518 | return lambda x: None 519 | 520 | class MyClass(object): 521 | 522 | some_attr = CrazyDescriptor() 523 | 524 | mock = create_autospec(MyClass) 525 | mock.some_attr(1) 526 | with self.assertRaises(TypeError): 527 | mock.some_attr() 528 | with self.assertRaises(TypeError): 529 | mock.some_attr(1, 2) 530 | 531 | 532 | def test_spec_has_function_not_in_bases(self): 533 | 534 | class CrazyClass(object): 535 | 536 | def __dir__(self): 537 | return super(CrazyClass, self).__dir__()+['crazy'] 538 | 539 | def __getattr__(self, item): 540 | if item == 'crazy': 541 | return lambda x: x 542 | raise AttributeError(item) 543 | 544 | inst = CrazyClass() 545 | with self.assertRaises(AttributeError): 546 | inst.other 547 | self.assertEqual(inst.crazy(42), 42) 548 | 549 | mock = create_autospec(inst) 550 | mock.crazy(42) 551 | with self.assertRaises(TypeError): 552 | mock.crazy() 553 | with self.assertRaises(TypeError): 554 | mock.crazy(1, 2) 555 | 556 | 557 | def test_builtin_functions_types(self): 558 | # we could replace builtin functions / methods with a function 559 | # with *args / **kwargs signature. Using the builtin method type 560 | # as a spec seems to work fairly well though. 561 | class BuiltinSubclass(list): 562 | def bar(self, arg): pass 563 | sorted = sorted 564 | attr = {} 565 | 566 | mock = create_autospec(BuiltinSubclass) 567 | mock.append(3) 568 | mock.append.assert_called_with(3) 569 | self.assertRaises(AttributeError, getattr, mock.append, 'foo') 570 | 571 | mock.bar('foo') 572 | mock.bar.assert_called_with('foo') 573 | self.assertRaises(TypeError, mock.bar, 'foo', 'bar') 574 | self.assertRaises(AttributeError, getattr, mock.bar, 'foo') 575 | 576 | mock.sorted([1, 2]) 577 | mock.sorted.assert_called_with([1, 2]) 578 | self.assertRaises(AttributeError, getattr, mock.sorted, 'foo') 579 | 580 | mock.attr.pop(3) 581 | mock.attr.pop.assert_called_with(3) 582 | self.assertRaises(AttributeError, getattr, mock.attr, 'foo') 583 | 584 | 585 | def test_method_calls(self): 586 | class Sub(SomeClass): 587 | attr = SomeClass() 588 | 589 | mock = create_autospec(Sub) 590 | mock.one(1, 2) 591 | mock.two() 592 | mock.three(3) 593 | 594 | expected = [call.one(1, 2), call.two(), call.three(3)] 595 | self.assertEqual(mock.method_calls, expected) 596 | 597 | mock.attr.one(1, 2) 598 | mock.attr.two() 599 | mock.attr.three(3) 600 | 601 | expected.extend( 602 | [call.attr.one(1, 2), call.attr.two(), call.attr.three(3)] 603 | ) 604 | self.assertEqual(mock.method_calls, expected) 605 | 606 | 607 | def test_magic_methods(self): 608 | class BuiltinSubclass(list): 609 | attr = {} 610 | 611 | mock = create_autospec(BuiltinSubclass) 612 | self.assertEqual(list(mock), []) 613 | self.assertRaises(TypeError, int, mock) 614 | self.assertRaises(TypeError, int, mock.attr) 615 | self.assertEqual(list(mock), []) 616 | 617 | self.assertIsInstance(mock['foo'], MagicMock) 618 | self.assertIsInstance(mock.attr['foo'], MagicMock) 619 | 620 | 621 | def test_spec_set(self): 622 | class Sub(SomeClass): 623 | attr = SomeClass() 624 | 625 | for spec in (Sub, Sub()): 626 | mock = create_autospec(spec, spec_set=True) 627 | self._check_someclass_mock(mock) 628 | 629 | self.assertRaises(AttributeError, setattr, mock, 'foo', 'bar') 630 | self.assertRaises(AttributeError, setattr, mock.attr, 'foo', 'bar') 631 | 632 | 633 | def test_descriptors(self): 634 | class Foo(object): 635 | @classmethod 636 | def f(cls, a, b): pass 637 | @staticmethod 638 | def g(a, b): pass 639 | 640 | class Bar(Foo): pass 641 | 642 | class Baz(SomeClass, Bar): pass 643 | 644 | for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()): 645 | mock = create_autospec(spec) 646 | mock.f(1, 2) 647 | mock.f.assert_called_once_with(1, 2) 648 | 649 | mock.g(3, 4) 650 | mock.g.assert_called_once_with(3, 4) 651 | 652 | 653 | def test_recursive(self): 654 | class A(object): 655 | def a(self): pass 656 | foo = 'foo bar baz' 657 | bar = foo 658 | 659 | A.B = A 660 | mock = create_autospec(A) 661 | 662 | mock() 663 | self.assertFalse(mock.B.called) 664 | 665 | mock.a() 666 | mock.B.a() 667 | self.assertEqual(mock.method_calls, [call.a(), call.B.a()]) 668 | 669 | self.assertIs(A.foo, A.bar) 670 | self.assertIsNot(mock.foo, mock.bar) 671 | mock.foo.lower() 672 | self.assertRaises(AssertionError, mock.bar.lower.assert_called_with) 673 | 674 | 675 | def test_spec_inheritance_for_classes(self): 676 | class Foo(object): 677 | def a(self, x): pass 678 | class Bar(object): 679 | def f(self, y): pass 680 | 681 | class_mock = create_autospec(Foo) 682 | 683 | self.assertIsNot(class_mock, class_mock()) 684 | 685 | for this_mock in class_mock, class_mock(): 686 | this_mock.a(x=5) 687 | this_mock.a.assert_called_with(x=5) 688 | this_mock.a.assert_called_with(5) 689 | self.assertRaises(TypeError, this_mock.a, 'foo', 'bar') 690 | self.assertRaises(AttributeError, getattr, this_mock, 'b') 691 | 692 | instance_mock = create_autospec(Foo()) 693 | instance_mock.a(5) 694 | instance_mock.a.assert_called_with(5) 695 | instance_mock.a.assert_called_with(x=5) 696 | self.assertRaises(TypeError, instance_mock.a, 'foo', 'bar') 697 | self.assertRaises(AttributeError, getattr, instance_mock, 'b') 698 | 699 | # The return value isn't isn't callable 700 | self.assertRaises(TypeError, instance_mock) 701 | 702 | instance_mock.Bar.f(6) 703 | instance_mock.Bar.f.assert_called_with(6) 704 | instance_mock.Bar.f.assert_called_with(y=6) 705 | self.assertRaises(AttributeError, getattr, instance_mock.Bar, 'g') 706 | 707 | instance_mock.Bar().f(6) 708 | instance_mock.Bar().f.assert_called_with(6) 709 | instance_mock.Bar().f.assert_called_with(y=6) 710 | self.assertRaises(AttributeError, getattr, instance_mock.Bar(), 'g') 711 | 712 | 713 | def test_inherit(self): 714 | class Foo(object): 715 | a = 3 716 | 717 | Foo.Foo = Foo 718 | 719 | # class 720 | mock = create_autospec(Foo) 721 | instance = mock() 722 | self.assertRaises(AttributeError, getattr, instance, 'b') 723 | 724 | attr_instance = mock.Foo() 725 | self.assertRaises(AttributeError, getattr, attr_instance, 'b') 726 | 727 | # instance 728 | mock = create_autospec(Foo()) 729 | self.assertRaises(AttributeError, getattr, mock, 'b') 730 | self.assertRaises(TypeError, mock) 731 | 732 | # attribute instance 733 | call_result = mock.Foo() 734 | self.assertRaises(AttributeError, getattr, call_result, 'b') 735 | 736 | 737 | def test_builtins(self): 738 | # used to fail with infinite recursion 739 | create_autospec(1) 740 | 741 | create_autospec(int) 742 | create_autospec('foo') 743 | create_autospec(str) 744 | create_autospec({}) 745 | create_autospec(dict) 746 | create_autospec([]) 747 | create_autospec(list) 748 | create_autospec(set()) 749 | create_autospec(set) 750 | create_autospec(1.0) 751 | create_autospec(float) 752 | create_autospec(1j) 753 | create_autospec(complex) 754 | create_autospec(False) 755 | create_autospec(True) 756 | 757 | 758 | def test_function(self): 759 | def f(a, b): pass 760 | 761 | mock = create_autospec(f) 762 | self.assertRaises(TypeError, mock) 763 | mock(1, 2) 764 | mock.assert_called_with(1, 2) 765 | mock.assert_called_with(1, b=2) 766 | mock.assert_called_with(a=1, b=2) 767 | 768 | f.f = f 769 | mock = create_autospec(f) 770 | self.assertRaises(TypeError, mock.f) 771 | mock.f(3, 4) 772 | mock.f.assert_called_with(3, 4) 773 | mock.f.assert_called_with(a=3, b=4) 774 | 775 | 776 | def test_skip_attributeerrors(self): 777 | class Raiser(object): 778 | def __get__(self, obj, type=None): 779 | if obj is None: 780 | raise AttributeError('Can only be accessed via an instance') 781 | 782 | class RaiserClass(object): 783 | raiser = Raiser() 784 | 785 | @staticmethod 786 | def existing(a, b): 787 | return a + b 788 | 789 | self.assertEqual(RaiserClass.existing(1, 2), 3) 790 | s = create_autospec(RaiserClass) 791 | self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3)) 792 | self.assertEqual(s.existing(1, 2), s.existing.return_value) 793 | self.assertRaises(AttributeError, lambda: s.nonexisting) 794 | 795 | # check we can fetch the raiser attribute and it has no spec 796 | obj = s.raiser 797 | obj.foo, obj.bar 798 | 799 | 800 | def test_signature_class(self): 801 | class Foo(object): 802 | def __init__(self, a, b=3): pass 803 | 804 | mock = create_autospec(Foo) 805 | 806 | self.assertRaises(TypeError, mock) 807 | mock(1) 808 | mock.assert_called_once_with(1) 809 | mock.assert_called_once_with(a=1) 810 | self.assertRaises(AssertionError, mock.assert_called_once_with, 2) 811 | 812 | mock(4, 5) 813 | mock.assert_called_with(4, 5) 814 | mock.assert_called_with(a=4, b=5) 815 | self.assertRaises(AssertionError, mock.assert_called_with, a=5, b=4) 816 | 817 | 818 | def test_class_with_no_init(self): 819 | # this used to raise an exception 820 | # due to trying to get a signature from object.__init__ 821 | class Foo(object): 822 | pass 823 | create_autospec(Foo) 824 | 825 | 826 | def test_signature_callable(self): 827 | class Callable(object): 828 | def __init__(self, x, y): pass 829 | def __call__(self, a): pass 830 | 831 | mock = create_autospec(Callable) 832 | mock(1, 2) 833 | mock.assert_called_once_with(1, 2) 834 | mock.assert_called_once_with(x=1, y=2) 835 | self.assertRaises(TypeError, mock, 'a') 836 | 837 | instance = mock(1, 2) 838 | self.assertRaises(TypeError, instance) 839 | instance(a='a') 840 | instance.assert_called_once_with('a') 841 | instance.assert_called_once_with(a='a') 842 | instance('a') 843 | instance.assert_called_with('a') 844 | instance.assert_called_with(a='a') 845 | 846 | mock = create_autospec(Callable(1, 2)) 847 | mock(a='a') 848 | mock.assert_called_once_with(a='a') 849 | self.assertRaises(TypeError, mock) 850 | mock('a') 851 | mock.assert_called_with('a') 852 | 853 | 854 | def test_signature_noncallable(self): 855 | class NonCallable(object): 856 | def __init__(self): 857 | pass 858 | 859 | mock = create_autospec(NonCallable) 860 | instance = mock() 861 | mock.assert_called_once_with() 862 | self.assertRaises(TypeError, mock, 'a') 863 | self.assertRaises(TypeError, instance) 864 | self.assertRaises(TypeError, instance, 'a') 865 | 866 | mock = create_autospec(NonCallable()) 867 | self.assertRaises(TypeError, mock) 868 | self.assertRaises(TypeError, mock, 'a') 869 | 870 | 871 | def test_create_autospec_none(self): 872 | class Foo(object): 873 | bar = None 874 | 875 | mock = create_autospec(Foo) 876 | none = mock.bar 877 | self.assertNotIsInstance(none, type(None)) 878 | 879 | none.foo() 880 | none.foo.assert_called_once_with() 881 | 882 | 883 | def test_autospec_functions_with_self_in_odd_place(self): 884 | class Foo(object): 885 | def f(a, self): pass 886 | 887 | a = create_autospec(Foo) 888 | a.f(10) 889 | a.f.assert_called_with(10) 890 | a.f.assert_called_with(self=10) 891 | a.f(self=10) 892 | a.f.assert_called_with(10) 893 | a.f.assert_called_with(self=10) 894 | 895 | 896 | def test_autospec_data_descriptor(self): 897 | class Descriptor(object): 898 | def __init__(self, value): 899 | self.value = value 900 | 901 | def __get__(self, obj, cls=None): 902 | return self 903 | 904 | def __set__(self, obj, value): pass 905 | 906 | class MyProperty(property): 907 | pass 908 | 909 | class Foo(object): 910 | __slots__ = ['slot'] 911 | 912 | @property 913 | def prop(self): pass 914 | 915 | @MyProperty 916 | def subprop(self): pass 917 | 918 | desc = Descriptor(42) 919 | 920 | foo = create_autospec(Foo) 921 | 922 | def check_data_descriptor(mock_attr): 923 | # Data descriptors don't have a spec. 924 | self.assertIsInstance(mock_attr, MagicMock) 925 | mock_attr(1, 2, 3) 926 | mock_attr.abc(4, 5, 6) 927 | mock_attr.assert_called_once_with(1, 2, 3) 928 | mock_attr.abc.assert_called_once_with(4, 5, 6) 929 | 930 | # property 931 | check_data_descriptor(foo.prop) 932 | # property subclass 933 | check_data_descriptor(foo.subprop) 934 | # class __slot__ 935 | check_data_descriptor(foo.slot) 936 | # plain data descriptor 937 | check_data_descriptor(foo.desc) 938 | 939 | 940 | def test_autospec_on_bound_builtin_function(self): 941 | meth = types.MethodType(time.ctime, time.time()) 942 | self.assertIsInstance(meth(), str) 943 | mocked = create_autospec(meth) 944 | 945 | # no signature, so no spec to check against 946 | mocked() 947 | mocked.assert_called_once_with() 948 | mocked.reset_mock() 949 | # but pypy gets this right: 950 | if IS_PYPY: 951 | with self.assertRaises(TypeError): 952 | mocked(4, 5, 6) 953 | else: 954 | mocked(4, 5, 6) 955 | mocked.assert_called_once_with(4, 5, 6) 956 | 957 | 958 | def test_autospec_getattr_partial_function(self): 959 | # bpo-32153 : getattr returning partial functions without 960 | # __name__ should not create AttributeError in create_autospec 961 | class Foo: 962 | 963 | def __getattr__(self, attribute): 964 | return partial(lambda name: name, attribute) 965 | 966 | proxy = Foo() 967 | autospec = create_autospec(proxy) 968 | self.assertFalse(hasattr(autospec, '__name__')) 969 | 970 | 971 | def test_autospec_signature_staticmethod(self): 972 | class Foo: 973 | @staticmethod 974 | def static_method(a, b=10, *, c): pass 975 | 976 | mock = create_autospec(Foo.__dict__['static_method']) 977 | self.assertEqual(inspect.signature(Foo.static_method), inspect.signature(mock)) 978 | 979 | 980 | def test_autospec_signature_classmethod(self): 981 | class Foo: 982 | @classmethod 983 | def class_method(cls, a, b=10, *, c): pass 984 | 985 | mock = create_autospec(Foo.__dict__['class_method']) 986 | self.assertEqual(inspect.signature(Foo.class_method), inspect.signature(mock)) 987 | 988 | 989 | def test_spec_inspect_signature(self): 990 | 991 | def myfunc(x, y): pass 992 | 993 | mock = create_autospec(myfunc) 994 | mock(1, 2) 995 | mock(x=1, y=2) 996 | 997 | self.assertEqual(inspect.signature(mock), inspect.signature(myfunc)) 998 | self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)]) 999 | self.assertRaises(TypeError, mock, 1) 1000 | 1001 | 1002 | def test_spec_inspect_signature_annotations(self): 1003 | 1004 | def foo(a: int, b: int=10, *, c:int) -> int: 1005 | return a + b + c 1006 | 1007 | self.assertEqual(foo(1, 2 , c=3), 6) 1008 | mock = create_autospec(foo) 1009 | mock(1, 2, c=3) 1010 | mock(1, c=3) 1011 | 1012 | self.assertEqual(inspect.signature(mock), inspect.signature(foo)) 1013 | self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)]) 1014 | self.assertRaises(TypeError, mock, 1) 1015 | self.assertRaises(TypeError, mock, 1, 2, 3, c=4) 1016 | 1017 | 1018 | def test_spec_function_no_name(self): 1019 | func = lambda: 'nope' 1020 | mock = create_autospec(func) 1021 | self.assertEqual(mock.__name__, 'funcopy') 1022 | 1023 | 1024 | def test_spec_function_assert_has_calls(self): 1025 | def f(a): pass 1026 | mock = create_autospec(f) 1027 | mock(1) 1028 | mock.assert_has_calls([call(1)]) 1029 | with self.assertRaises(AssertionError): 1030 | mock.assert_has_calls([call(2)]) 1031 | 1032 | 1033 | def test_spec_function_assert_any_call(self): 1034 | def f(a): pass 1035 | mock = create_autospec(f) 1036 | mock(1) 1037 | mock.assert_any_call(1) 1038 | with self.assertRaises(AssertionError): 1039 | mock.assert_any_call(2) 1040 | 1041 | 1042 | def test_spec_function_reset_mock(self): 1043 | def f(a): pass 1044 | rv = Mock() 1045 | mock = create_autospec(f, return_value=rv) 1046 | mock(1)(2) 1047 | self.assertEqual(mock.mock_calls, [call(1)]) 1048 | self.assertEqual(rv.mock_calls, [call(2)]) 1049 | mock.reset_mock() 1050 | self.assertEqual(mock.mock_calls, []) 1051 | self.assertEqual(rv.mock_calls, []) 1052 | 1053 | @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") 1054 | def test_dataclass_post_init(self): 1055 | @dataclass 1056 | class WithPostInit: 1057 | a: int = field(init=False) 1058 | b: int = field(init=False) 1059 | def __post_init__(self): 1060 | self.a = 1 1061 | self.b = 2 1062 | 1063 | for mock in [ 1064 | create_autospec(WithPostInit, instance=True), 1065 | create_autospec(WithPostInit()), 1066 | ]: 1067 | with self.subTest(mock=mock): 1068 | self.assertIsInstance(mock.a, int) 1069 | self.assertIsInstance(mock.b, int) 1070 | 1071 | # Classes do not have these fields: 1072 | mock = create_autospec(WithPostInit) 1073 | msg = "Mock object has no attribute" 1074 | with self.assertRaisesRegex(AttributeError, msg): 1075 | mock.a 1076 | with self.assertRaisesRegex(AttributeError, msg): 1077 | mock.b 1078 | 1079 | @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") 1080 | def test_dataclass_default(self): 1081 | @dataclass 1082 | class WithDefault: 1083 | a: int 1084 | b: int = 0 1085 | 1086 | for mock in [ 1087 | create_autospec(WithDefault, instance=True), 1088 | create_autospec(WithDefault(1)), 1089 | ]: 1090 | with self.subTest(mock=mock): 1091 | self.assertIsInstance(mock.a, int) 1092 | self.assertIsInstance(mock.b, int) 1093 | 1094 | @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") 1095 | def test_dataclass_with_method(self): 1096 | @dataclass 1097 | class WithMethod: 1098 | a: int 1099 | def b(self) -> int: 1100 | return 1 # pragma: no cover 1101 | 1102 | for mock in [ 1103 | create_autospec(WithMethod, instance=True), 1104 | create_autospec(WithMethod(1)), 1105 | ]: 1106 | with self.subTest(mock=mock): 1107 | self.assertIsInstance(mock.a, int) 1108 | mock.b.assert_not_called() 1109 | 1110 | @pytest.mark.skipif(sys.version_info < (3, 7), reason="requires python 3.7 or higher") 1111 | def test_dataclass_with_non_fields(self): 1112 | @dataclass 1113 | class WithNonFields: 1114 | a: ClassVar[int] 1115 | b: InitVar[int] 1116 | 1117 | msg = "Mock object has no attribute" 1118 | for mock in [ 1119 | create_autospec(WithNonFields, instance=True), 1120 | create_autospec(WithNonFields(1)), 1121 | ]: 1122 | with self.subTest(mock=mock): 1123 | with self.assertRaisesRegex(AttributeError, msg): 1124 | mock.a 1125 | with self.assertRaisesRegex(AttributeError, msg): 1126 | mock.b 1127 | 1128 | class TestCallList(unittest.TestCase): 1129 | 1130 | def test_args_list_contains_call_list(self): 1131 | mock = Mock() 1132 | self.assertIsInstance(mock.call_args_list, _CallList) 1133 | 1134 | mock(1, 2) 1135 | mock(a=3) 1136 | mock(3, 4) 1137 | mock(b=6) 1138 | 1139 | for kall in call(1, 2), call(a=3), call(3, 4), call(b=6): 1140 | self.assertIn(kall, mock.call_args_list) 1141 | 1142 | calls = [call(a=3), call(3, 4)] 1143 | self.assertIn(calls, mock.call_args_list) 1144 | calls = [call(1, 2), call(a=3)] 1145 | self.assertIn(calls, mock.call_args_list) 1146 | calls = [call(3, 4), call(b=6)] 1147 | self.assertIn(calls, mock.call_args_list) 1148 | calls = [call(3, 4)] 1149 | self.assertIn(calls, mock.call_args_list) 1150 | 1151 | self.assertNotIn(call('fish'), mock.call_args_list) 1152 | self.assertNotIn([call('fish')], mock.call_args_list) 1153 | 1154 | 1155 | def test_call_list_str(self): 1156 | mock = Mock() 1157 | mock(1, 2) 1158 | mock.foo(a=3) 1159 | mock.foo.bar().baz('fish', cat='dog') 1160 | 1161 | expected = ( 1162 | "[call(1, 2),\n" 1163 | " call.foo(a=3),\n" 1164 | " call.foo.bar(),\n" 1165 | " call.foo.bar().baz('fish', cat='dog')]" 1166 | ) 1167 | self.assertEqual(str(mock.mock_calls), expected) 1168 | 1169 | 1170 | def test_propertymock(self): 1171 | p = patch('%s.SomeClass.one' % __name__, new_callable=PropertyMock) 1172 | mock = p.start() 1173 | try: 1174 | SomeClass.one 1175 | mock.assert_called_once_with() 1176 | 1177 | s = SomeClass() 1178 | s.one 1179 | mock.assert_called_with() 1180 | self.assertEqual(mock.mock_calls, [call(), call()]) 1181 | 1182 | s.one = 3 1183 | self.assertEqual(mock.mock_calls, [call(), call(), call(3)]) 1184 | finally: 1185 | p.stop() 1186 | 1187 | 1188 | def test_propertymock_bare(self): 1189 | m = MagicMock() 1190 | p = PropertyMock() 1191 | type(m).foo = p 1192 | 1193 | returned = m.foo 1194 | p.assert_called_once_with() 1195 | self.assertIsInstance(returned, MagicMock) 1196 | self.assertNotIsInstance(returned, PropertyMock) 1197 | 1198 | 1199 | def test_propertymock_returnvalue(self): 1200 | m = MagicMock() 1201 | p = PropertyMock(return_value=42) 1202 | type(m).foo = p 1203 | 1204 | returned = m.foo 1205 | p.assert_called_once_with() 1206 | self.assertEqual(returned, 42) 1207 | self.assertNotIsInstance(returned, PropertyMock) 1208 | 1209 | 1210 | def test_propertymock_side_effect(self): 1211 | m = MagicMock() 1212 | p = PropertyMock(side_effect=ValueError) 1213 | type(m).foo = p 1214 | 1215 | with self.assertRaises(ValueError): 1216 | m.foo 1217 | p.assert_called_once_with() 1218 | 1219 | 1220 | def test_propertymock_attach(self): 1221 | m = Mock() 1222 | p = PropertyMock() 1223 | type(m).foo = p 1224 | m.attach_mock(p, 'foo') 1225 | self.assertEqual(m.mock_calls, []) 1226 | 1227 | 1228 | class TestCallablePredicate(unittest.TestCase): 1229 | 1230 | def test_type(self): 1231 | for obj in [str, bytes, int, list, tuple, SomeClass]: 1232 | self.assertTrue(_callable(obj)) 1233 | 1234 | def test_call_magic_method(self): 1235 | class Callable: 1236 | def __call__(self): pass 1237 | instance = Callable() 1238 | self.assertTrue(_callable(instance)) 1239 | 1240 | def test_staticmethod(self): 1241 | class WithStaticMethod: 1242 | @staticmethod 1243 | def staticfunc(): pass 1244 | self.assertTrue(_callable(WithStaticMethod.staticfunc)) 1245 | 1246 | def test_non_callable_staticmethod(self): 1247 | class BadStaticMethod: 1248 | not_callable = staticmethod(None) 1249 | self.assertFalse(_callable(BadStaticMethod.not_callable)) 1250 | 1251 | def test_classmethod(self): 1252 | class WithClassMethod: 1253 | @classmethod 1254 | def classfunc(cls): pass 1255 | self.assertTrue(_callable(WithClassMethod.classfunc)) 1256 | 1257 | def test_non_callable_classmethod(self): 1258 | class BadClassMethod: 1259 | not_callable = classmethod(None) 1260 | self.assertFalse(_callable(BadClassMethod.not_callable)) 1261 | 1262 | 1263 | if __name__ == '__main__': 1264 | unittest.main() 1265 | -------------------------------------------------------------------------------- /mock/tests/testmagicmethods.py: -------------------------------------------------------------------------------- 1 | import math 2 | import unittest 3 | import os 4 | from mock import AsyncMock, Mock, MagicMock 5 | from mock.backports import iscoroutinefunction 6 | from mock.mock import _magics 7 | 8 | 9 | class TestMockingMagicMethods(unittest.TestCase): 10 | 11 | def test_deleting_magic_methods(self): 12 | mock = Mock() 13 | self.assertFalse(hasattr(mock, '__getitem__')) 14 | 15 | mock.__getitem__ = Mock() 16 | self.assertTrue(hasattr(mock, '__getitem__')) 17 | 18 | del mock.__getitem__ 19 | self.assertFalse(hasattr(mock, '__getitem__')) 20 | 21 | 22 | def test_magicmock_del(self): 23 | mock = MagicMock() 24 | # before using getitem 25 | del mock.__getitem__ 26 | self.assertRaises(TypeError, lambda: mock['foo']) 27 | 28 | mock = MagicMock() 29 | # this time use it first 30 | mock['foo'] 31 | del mock.__getitem__ 32 | self.assertRaises(TypeError, lambda: mock['foo']) 33 | 34 | 35 | def test_magic_method_wrapping(self): 36 | mock = Mock() 37 | def f(self, name): 38 | return self, 'fish' 39 | 40 | mock.__getitem__ = f 41 | self.assertIsNot(mock.__getitem__, f) 42 | self.assertEqual(mock['foo'], (mock, 'fish')) 43 | self.assertEqual(mock.__getitem__('foo'), (mock, 'fish')) 44 | 45 | mock.__getitem__ = mock 46 | self.assertIs(mock.__getitem__, mock) 47 | 48 | 49 | def test_magic_methods_isolated_between_mocks(self): 50 | mock1 = Mock() 51 | mock2 = Mock() 52 | 53 | mock1.__iter__ = Mock(return_value=iter([])) 54 | self.assertEqual(list(mock1), []) 55 | self.assertRaises(TypeError, lambda: list(mock2)) 56 | 57 | 58 | def test_repr(self): 59 | mock = Mock() 60 | self.assertEqual(repr(mock), "" % id(mock)) 61 | mock.__repr__ = lambda s: 'foo' 62 | self.assertEqual(repr(mock), 'foo') 63 | 64 | 65 | def test_str(self): 66 | mock = Mock() 67 | self.assertEqual(str(mock), object.__str__(mock)) 68 | mock.__str__ = lambda s: 'foo' 69 | self.assertEqual(str(mock), 'foo') 70 | 71 | 72 | def test_dict_methods(self): 73 | mock = Mock() 74 | 75 | self.assertRaises(TypeError, lambda: mock['foo']) 76 | def _del(): 77 | del mock['foo'] 78 | def _set(): 79 | mock['foo'] = 3 80 | self.assertRaises(TypeError, _del) 81 | self.assertRaises(TypeError, _set) 82 | 83 | _dict = {} 84 | def getitem(s, name): 85 | return _dict[name] 86 | def setitem(s, name, value): 87 | _dict[name] = value 88 | def delitem(s, name): 89 | del _dict[name] 90 | 91 | mock.__setitem__ = setitem 92 | mock.__getitem__ = getitem 93 | mock.__delitem__ = delitem 94 | 95 | self.assertRaises(KeyError, lambda: mock['foo']) 96 | mock['foo'] = 'bar' 97 | self.assertEqual(_dict, {'foo': 'bar'}) 98 | self.assertEqual(mock['foo'], 'bar') 99 | del mock['foo'] 100 | self.assertEqual(_dict, {}) 101 | 102 | 103 | def test_numeric(self): 104 | original = mock = Mock() 105 | mock.value = 0 106 | 107 | self.assertRaises(TypeError, lambda: mock + 3) 108 | 109 | def add(self, other): 110 | mock.value += other 111 | return self 112 | mock.__add__ = add 113 | self.assertEqual(mock + 3, mock) 114 | self.assertEqual(mock.value, 3) 115 | 116 | del mock.__add__ 117 | def iadd(mock): 118 | mock += 3 119 | self.assertRaises(TypeError, iadd, mock) 120 | mock.__iadd__ = add 121 | mock += 6 122 | self.assertEqual(mock, original) 123 | self.assertEqual(mock.value, 9) 124 | 125 | self.assertRaises(TypeError, lambda: 3 + mock) 126 | mock.__radd__ = add 127 | self.assertEqual(7 + mock, mock) 128 | self.assertEqual(mock.value, 16) 129 | 130 | def test_division(self): 131 | original = mock = Mock() 132 | mock.value = 32 133 | self.assertRaises(TypeError, lambda: mock / 2) 134 | 135 | def truediv(self, other): 136 | mock.value /= other 137 | return self 138 | mock.__truediv__ = truediv 139 | self.assertEqual(mock / 2, mock) 140 | self.assertEqual(mock.value, 16) 141 | 142 | del mock.__truediv__ 143 | def itruediv(mock): 144 | mock /= 4 145 | self.assertRaises(TypeError, itruediv, mock) 146 | mock.__itruediv__ = truediv 147 | mock /= 8 148 | self.assertEqual(mock, original) 149 | self.assertEqual(mock.value, 2) 150 | 151 | self.assertRaises(TypeError, lambda: 8 / mock) 152 | mock.__rtruediv__ = truediv 153 | self.assertEqual(0.5 / mock, mock) 154 | self.assertEqual(mock.value, 4) 155 | 156 | def test_hash(self): 157 | mock = Mock() 158 | # test delegation 159 | self.assertEqual(hash(mock), Mock.__hash__(mock)) 160 | 161 | def _hash(s): 162 | return 3 163 | mock.__hash__ = _hash 164 | self.assertEqual(hash(mock), 3) 165 | 166 | 167 | def test_nonzero(self): 168 | m = Mock() 169 | self.assertTrue(bool(m)) 170 | 171 | m.__bool__ = lambda s: False 172 | self.assertFalse(bool(m)) 173 | 174 | 175 | def test_comparison(self): 176 | mock = Mock() 177 | def comp(s, o): 178 | return True 179 | mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp 180 | self. assertTrue(mock < 3) 181 | self. assertTrue(mock > 3) 182 | self. assertTrue(mock <= 3) 183 | self. assertTrue(mock >= 3) 184 | 185 | self.assertRaises(TypeError, lambda: MagicMock() < object()) 186 | self.assertRaises(TypeError, lambda: object() < MagicMock()) 187 | self.assertRaises(TypeError, lambda: MagicMock() < MagicMock()) 188 | self.assertRaises(TypeError, lambda: MagicMock() > object()) 189 | self.assertRaises(TypeError, lambda: object() > MagicMock()) 190 | self.assertRaises(TypeError, lambda: MagicMock() > MagicMock()) 191 | self.assertRaises(TypeError, lambda: MagicMock() <= object()) 192 | self.assertRaises(TypeError, lambda: object() <= MagicMock()) 193 | self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock()) 194 | self.assertRaises(TypeError, lambda: MagicMock() >= object()) 195 | self.assertRaises(TypeError, lambda: object() >= MagicMock()) 196 | self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock()) 197 | 198 | 199 | def test_equality(self): 200 | for mock in Mock(), MagicMock(): 201 | self.assertEqual(mock == mock, True) 202 | self.assertIsInstance(mock == mock, bool) 203 | self.assertEqual(mock != mock, False) 204 | self.assertIsInstance(mock != mock, bool) 205 | self.assertEqual(mock == object(), False) 206 | self.assertEqual(mock != object(), True) 207 | 208 | def eq(self, other): 209 | return other == 3 210 | mock.__eq__ = eq 211 | self.assertTrue(mock == 3) 212 | self.assertFalse(mock == 4) 213 | 214 | def ne(self, other): 215 | return other == 3 216 | mock.__ne__ = ne 217 | self.assertTrue(mock != 3) 218 | self.assertFalse(mock != 4) 219 | 220 | mock = MagicMock() 221 | mock.__eq__.return_value = True 222 | self.assertIsInstance(mock == 3, bool) 223 | self.assertEqual(mock == 3, True) 224 | 225 | mock.__ne__.return_value = False 226 | self.assertIsInstance(mock != 3, bool) 227 | self.assertEqual(mock != 3, False) 228 | 229 | 230 | def test_len_contains_iter(self): 231 | mock = Mock() 232 | 233 | self.assertRaises(TypeError, len, mock) 234 | self.assertRaises(TypeError, iter, mock) 235 | self.assertRaises(TypeError, lambda: 'foo' in mock) 236 | 237 | mock.__len__ = lambda s: 6 238 | self.assertEqual(len(mock), 6) 239 | 240 | mock.__contains__ = lambda s, o: o == 3 241 | self.assertIn(3, mock) 242 | self.assertNotIn(6, mock) 243 | 244 | mock.__iter__ = lambda s: iter('foobarbaz') 245 | self.assertEqual(list(mock), list('foobarbaz')) 246 | 247 | 248 | def test_magicmock(self): 249 | mock = MagicMock() 250 | 251 | mock.__iter__.return_value = iter([1, 2, 3]) 252 | self.assertEqual(list(mock), [1, 2, 3]) 253 | 254 | getattr(mock, '__bool__').return_value = False 255 | self.assertFalse(hasattr(mock, '__nonzero__')) 256 | self.assertFalse(bool(mock)) 257 | 258 | for entry in _magics: 259 | self.assertTrue(hasattr(mock, entry)) 260 | self.assertFalse(hasattr(mock, '__imaginary__')) 261 | 262 | 263 | def test_magic_mock_equality(self): 264 | mock = MagicMock() 265 | self.assertIsInstance(mock == object(), bool) 266 | self.assertIsInstance(mock != object(), bool) 267 | 268 | self.assertEqual(mock == object(), False) 269 | self.assertEqual(mock != object(), True) 270 | self.assertEqual(mock == mock, True) 271 | self.assertEqual(mock != mock, False) 272 | 273 | def test_asyncmock_defaults(self): 274 | mock = AsyncMock() 275 | self.assertEqual(int(mock), 1) 276 | self.assertEqual(complex(mock), 1j) 277 | self.assertEqual(float(mock), 1.0) 278 | self.assertNotIn(object(), mock) 279 | self.assertEqual(len(mock), 0) 280 | self.assertEqual(list(mock), []) 281 | self.assertEqual(hash(mock), object.__hash__(mock)) 282 | self.assertEqual(str(mock), object.__str__(mock)) 283 | self.assertTrue(bool(mock)) 284 | self.assertEqual(round(mock), mock.__round__()) 285 | self.assertEqual(math.trunc(mock), mock.__trunc__()) 286 | self.assertEqual(math.floor(mock), mock.__floor__()) 287 | self.assertEqual(math.ceil(mock), mock.__ceil__()) 288 | self.assertTrue(iscoroutinefunction(mock.__aexit__)) 289 | self.assertTrue(iscoroutinefunction(mock.__aenter__)) 290 | self.assertIsInstance(mock.__aenter__, AsyncMock) 291 | self.assertIsInstance(mock.__aexit__, AsyncMock) 292 | 293 | # in Python 3 oct and hex use __index__ 294 | # so these tests are for __index__ in py3k 295 | self.assertEqual(oct(mock), '0o1') 296 | self.assertEqual(hex(mock), '0x1') 297 | # how to test __sizeof__ ? 298 | 299 | def test_magicmock_defaults(self): 300 | mock = MagicMock() 301 | self.assertEqual(int(mock), 1) 302 | self.assertEqual(complex(mock), 1j) 303 | self.assertEqual(float(mock), 1.0) 304 | self.assertNotIn(object(), mock) 305 | self.assertEqual(len(mock), 0) 306 | self.assertEqual(list(mock), []) 307 | self.assertEqual(hash(mock), object.__hash__(mock)) 308 | self.assertEqual(str(mock), object.__str__(mock)) 309 | self.assertTrue(bool(mock)) 310 | self.assertEqual(round(mock), mock.__round__()) 311 | self.assertEqual(math.trunc(mock), mock.__trunc__()) 312 | self.assertEqual(math.floor(mock), mock.__floor__()) 313 | self.assertEqual(math.ceil(mock), mock.__ceil__()) 314 | self.assertTrue(iscoroutinefunction(mock.__aexit__)) 315 | self.assertTrue(iscoroutinefunction(mock.__aenter__)) 316 | self.assertIsInstance(mock.__aenter__, AsyncMock) 317 | self.assertIsInstance(mock.__aexit__, AsyncMock) 318 | 319 | # in Python 3 oct and hex use __index__ 320 | # so these tests are for __index__ in py3k 321 | self.assertEqual(oct(mock), '0o1') 322 | self.assertEqual(hex(mock), '0x1') 323 | # how to test __sizeof__ ? 324 | 325 | 326 | def test_magic_methods_fspath(self): 327 | mock = MagicMock() 328 | expected_path = mock.__fspath__() 329 | mock.reset_mock() 330 | 331 | self.assertEqual(os.fspath(mock), expected_path) 332 | mock.__fspath__.assert_called_once() 333 | 334 | def test_magic_mock_does_not_reset_magic_returns(self): 335 | # https://github.com/python/cpython/issues/123934 336 | for reset in (True, False): 337 | with self.subTest(reset=reset): 338 | mm = MagicMock() 339 | self.assertIs(type(mm.__str__()), str) 340 | mm.__str__.assert_called_once() 341 | 342 | self.assertIs(type(mm.__hash__()), int) 343 | mm.__hash__.assert_called_once() 344 | 345 | for _ in range(3): 346 | # Repeat reset several times to be sure: 347 | mm.reset_mock(return_value=reset) 348 | 349 | self.assertIs(type(mm.__str__()), str) 350 | mm.__str__.assert_called_once() 351 | 352 | self.assertIs(type(mm.__hash__()), int) 353 | mm.__hash__.assert_called_once() 354 | 355 | def test_magic_mock_resets_manual_mocks(self): 356 | mm = MagicMock() 357 | mm.__iter__ = MagicMock(return_value=iter([1])) 358 | mm.custom = MagicMock(return_value=2) 359 | self.assertEqual(list(iter(mm)), [1]) 360 | self.assertEqual(mm.custom(), 2) 361 | 362 | mm.reset_mock(return_value=True) 363 | self.assertEqual(list(iter(mm)), []) 364 | self.assertIsInstance(mm.custom(), MagicMock) 365 | 366 | def test_magic_mock_resets_manual_mocks_empty_iter(self): 367 | mm = MagicMock() 368 | mm.__iter__.return_value = [] 369 | self.assertEqual(list(iter(mm)), []) 370 | 371 | mm.reset_mock(return_value=True) 372 | self.assertEqual(list(iter(mm)), []) 373 | 374 | def test_magic_methods_and_spec(self): 375 | class Iterable(object): 376 | def __iter__(self): pass 377 | 378 | mock = Mock(spec=Iterable) 379 | self.assertRaises(AttributeError, lambda: mock.__iter__) 380 | 381 | mock.__iter__ = Mock(return_value=iter([])) 382 | self.assertEqual(list(mock), []) 383 | 384 | class NonIterable(object): 385 | pass 386 | mock = Mock(spec=NonIterable) 387 | self.assertRaises(AttributeError, lambda: mock.__iter__) 388 | 389 | def set_int(): 390 | mock.__int__ = Mock(return_value=iter([])) 391 | self.assertRaises(AttributeError, set_int) 392 | 393 | mock = MagicMock(spec=Iterable) 394 | self.assertEqual(list(mock), []) 395 | self.assertRaises(AttributeError, set_int) 396 | 397 | 398 | def test_magic_methods_and_spec_set(self): 399 | class Iterable(object): 400 | def __iter__(self): pass 401 | 402 | mock = Mock(spec_set=Iterable) 403 | self.assertRaises(AttributeError, lambda: mock.__iter__) 404 | 405 | mock.__iter__ = Mock(return_value=iter([])) 406 | self.assertEqual(list(mock), []) 407 | 408 | class NonIterable(object): 409 | pass 410 | mock = Mock(spec_set=NonIterable) 411 | self.assertRaises(AttributeError, lambda: mock.__iter__) 412 | 413 | def set_int(): 414 | mock.__int__ = Mock(return_value=iter([])) 415 | self.assertRaises(AttributeError, set_int) 416 | 417 | mock = MagicMock(spec_set=Iterable) 418 | self.assertEqual(list(mock), []) 419 | self.assertRaises(AttributeError, set_int) 420 | 421 | 422 | def test_setting_unsupported_magic_method(self): 423 | mock = MagicMock() 424 | def set_setattr(): 425 | mock.__setattr__ = lambda self, name: None 426 | self.assertRaisesRegex(AttributeError, 427 | "Attempting to set unsupported magic method '__setattr__'.", 428 | set_setattr 429 | ) 430 | 431 | 432 | def test_attributes_and_return_value(self): 433 | mock = MagicMock() 434 | attr = mock.foo 435 | def _get_type(obj): 436 | # the type of every mock (or magicmock) is a custom subclass 437 | # so the real type is the second in the mro 438 | return type(obj).__mro__[1] 439 | self.assertEqual(_get_type(attr), MagicMock) 440 | 441 | returned = mock() 442 | self.assertEqual(_get_type(returned), MagicMock) 443 | 444 | 445 | def test_magic_methods_are_magic_mocks(self): 446 | mock = MagicMock() 447 | self.assertIsInstance(mock.__getitem__, MagicMock) 448 | 449 | mock[1][2].__getitem__.return_value = 3 450 | self.assertEqual(mock[1][2][3], 3) 451 | 452 | 453 | def test_magic_method_reset_mock(self): 454 | mock = MagicMock() 455 | str(mock) 456 | self.assertTrue(mock.__str__.called) 457 | mock.reset_mock() 458 | self.assertFalse(mock.__str__.called) 459 | 460 | 461 | def test_dir(self): 462 | # overriding the default implementation 463 | for mock in Mock(), MagicMock(): 464 | def _dir(self): 465 | return ['foo'] 466 | mock.__dir__ = _dir 467 | self.assertEqual(dir(mock), ['foo']) 468 | 469 | 470 | def test_bound_methods(self): 471 | m = Mock() 472 | 473 | # XXXX should this be an expected failure instead? 474 | 475 | # this seems like it should work, but is hard to do without introducing 476 | # other api inconsistencies. Failure message could be better though. 477 | m.__iter__ = [3].__iter__ 478 | self.assertRaises(TypeError, iter, m) 479 | 480 | 481 | def test_magic_method_type(self): 482 | class Foo(MagicMock): 483 | pass 484 | 485 | foo = Foo() 486 | self.assertIsInstance(foo.__int__, Foo) 487 | 488 | 489 | def test_descriptor_from_class(self): 490 | m = MagicMock() 491 | type(m).__str__.return_value = 'foo' 492 | self.assertEqual(str(m), 'foo') 493 | 494 | 495 | def test_iterable_as_iter_return_value(self): 496 | m = MagicMock() 497 | m.__iter__.return_value = [1, 2, 3] 498 | self.assertEqual(list(m), [1, 2, 3]) 499 | self.assertEqual(list(m), [1, 2, 3]) 500 | 501 | m.__iter__.return_value = iter([4, 5, 6]) 502 | self.assertEqual(list(m), [4, 5, 6]) 503 | self.assertEqual(list(m), []) 504 | 505 | 506 | def test_matmul(self): 507 | m = MagicMock() 508 | self.assertIsInstance(m @ 1, MagicMock) 509 | m.__matmul__.return_value = 42 510 | m.__rmatmul__.return_value = 666 511 | m.__imatmul__.return_value = 24 512 | self.assertEqual(m @ 1, 42) 513 | self.assertEqual(1 @ m, 666) 514 | m @= 24 515 | self.assertEqual(m, 24) 516 | 517 | def test_divmod_and_rdivmod(self): 518 | m = MagicMock() 519 | self.assertIsInstance(divmod(5, m), MagicMock) 520 | m.__divmod__.return_value = (2, 1) 521 | self.assertEqual(divmod(m, 2), (2, 1)) 522 | m = MagicMock() 523 | foo = divmod(2, m) 524 | self.assertIsInstance(foo, MagicMock) 525 | foo_direct = m.__divmod__(2) 526 | self.assertIsInstance(foo_direct, MagicMock) 527 | bar = divmod(m, 2) 528 | self.assertIsInstance(bar, MagicMock) 529 | bar_direct = m.__rdivmod__(2) 530 | self.assertIsInstance(bar_direct, MagicMock) 531 | 532 | # http://bugs.python.org/issue23310 533 | # Check if you can change behaviour of magic methods in MagicMock init 534 | def test_magic_in_initialization(self): 535 | m = MagicMock(**{'__str__.return_value': "12"}) 536 | self.assertEqual(str(m), "12") 537 | 538 | def test_changing_magic_set_in_initialization(self): 539 | m = MagicMock(**{'__str__.return_value': "12"}) 540 | m.__str__.return_value = "13" 541 | self.assertEqual(str(m), "13") 542 | m = MagicMock(**{'__str__.return_value': "12"}) 543 | m.configure_mock(**{'__str__.return_value': "14"}) 544 | self.assertEqual(str(m), "14") 545 | 546 | 547 | if __name__ == '__main__': 548 | unittest.main() 549 | -------------------------------------------------------------------------------- /mock/tests/testsealable.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import mock 3 | 4 | 5 | class SampleObject: 6 | 7 | def method_sample1(self): pass 8 | 9 | def method_sample2(self): pass 10 | 11 | 12 | class TestSealable(unittest.TestCase): 13 | 14 | def test_attributes_return_more_mocks_by_default(self): 15 | m = mock.Mock() 16 | 17 | self.assertIsInstance(m.test, mock.Mock) 18 | self.assertIsInstance(m.test(), mock.Mock) 19 | self.assertIsInstance(m.test().test2(), mock.Mock) 20 | 21 | def test_new_attributes_cannot_be_accessed_on_seal(self): 22 | m = mock.Mock() 23 | 24 | mock.seal(m) 25 | with self.assertRaises(AttributeError): 26 | m.test 27 | with self.assertRaises(AttributeError): 28 | m() 29 | 30 | def test_new_attributes_cannot_be_set_on_seal(self): 31 | m = mock.Mock() 32 | 33 | mock.seal(m) 34 | with self.assertRaises(AttributeError): 35 | m.test = 1 36 | 37 | def test_existing_attributes_can_be_set_on_seal(self): 38 | m = mock.Mock() 39 | m.test.test2 = 1 40 | 41 | mock.seal(m) 42 | m.test.test2 = 2 43 | self.assertEqual(m.test.test2, 2) 44 | 45 | def test_new_attributes_cannot_be_set_on_child_of_seal(self): 46 | m = mock.Mock() 47 | m.test.test2 = 1 48 | 49 | mock.seal(m) 50 | with self.assertRaises(AttributeError): 51 | m.test.test3 = 1 52 | 53 | def test_existing_attributes_allowed_after_seal(self): 54 | m = mock.Mock() 55 | 56 | m.test.return_value = 3 57 | 58 | mock.seal(m) 59 | self.assertEqual(m.test(), 3) 60 | 61 | def test_initialized_attributes_allowed_after_seal(self): 62 | m = mock.Mock(test_value=1) 63 | 64 | mock.seal(m) 65 | self.assertEqual(m.test_value, 1) 66 | 67 | def test_call_on_sealed_mock_fails(self): 68 | m = mock.Mock() 69 | 70 | mock.seal(m) 71 | with self.assertRaises(AttributeError): 72 | m() 73 | 74 | def test_call_on_defined_sealed_mock_succeeds(self): 75 | m = mock.Mock(return_value=5) 76 | 77 | mock.seal(m) 78 | self.assertEqual(m(), 5) 79 | 80 | def test_seals_recurse_on_added_attributes(self): 81 | m = mock.Mock() 82 | 83 | m.test1.test2().test3 = 4 84 | 85 | mock.seal(m) 86 | self.assertEqual(m.test1.test2().test3, 4) 87 | with self.assertRaises(AttributeError): 88 | m.test1.test2().test4 89 | with self.assertRaises(AttributeError): 90 | m.test1.test3 91 | 92 | def test_seals_recurse_on_magic_methods(self): 93 | m = mock.MagicMock() 94 | 95 | m.test1.test2["a"].test3 = 4 96 | m.test1.test3[2:5].test3 = 4 97 | 98 | mock.seal(m) 99 | self.assertEqual(m.test1.test2["a"].test3, 4) 100 | self.assertEqual(m.test1.test2[2:5].test3, 4) 101 | with self.assertRaises(AttributeError): 102 | m.test1.test2["a"].test4 103 | with self.assertRaises(AttributeError): 104 | m.test1.test3[2:5].test4 105 | 106 | def test_seals_dont_recurse_on_manual_attributes(self): 107 | m = mock.Mock(name="root_mock") 108 | 109 | m.test1.test2 = mock.Mock(name="not_sealed") 110 | m.test1.test2.test3 = 4 111 | 112 | mock.seal(m) 113 | self.assertEqual(m.test1.test2.test3, 4) 114 | m.test1.test2.test4 # Does not raise 115 | m.test1.test2.test4 = 1 # Does not raise 116 | 117 | def test_integration_with_spec_att_definition(self): 118 | """You are not restricted when using mock with spec""" 119 | m = mock.Mock(SampleObject) 120 | 121 | m.attr_sample1 = 1 122 | m.attr_sample3 = 3 123 | 124 | mock.seal(m) 125 | self.assertEqual(m.attr_sample1, 1) 126 | self.assertEqual(m.attr_sample3, 3) 127 | with self.assertRaises(AttributeError): 128 | m.attr_sample2 129 | 130 | def test_integration_with_spec_method_definition(self): 131 | """You need to define the methods, even if they are in the spec""" 132 | m = mock.Mock(SampleObject) 133 | 134 | m.method_sample1.return_value = 1 135 | 136 | mock.seal(m) 137 | self.assertEqual(m.method_sample1(), 1) 138 | with self.assertRaises(AttributeError): 139 | m.method_sample2() 140 | 141 | def test_integration_with_spec_method_definition_respects_spec(self): 142 | """You cannot define methods out of the spec""" 143 | m = mock.Mock(SampleObject) 144 | 145 | with self.assertRaises(AttributeError): 146 | m.method_sample3.return_value = 3 147 | 148 | def test_sealed_exception_has_attribute_name(self): 149 | m = mock.Mock() 150 | 151 | mock.seal(m) 152 | with self.assertRaises(AttributeError) as cm: 153 | m.SECRETE_name 154 | self.assertIn("SECRETE_name", str(cm.exception)) 155 | 156 | def test_attribute_chain_is_maintained(self): 157 | m = mock.Mock(name="mock_name") 158 | m.test1.test2.test3.test4 159 | 160 | mock.seal(m) 161 | with self.assertRaises(AttributeError) as cm: 162 | m.test1.test2.test3.test4.boom 163 | self.assertIn("mock_name.test1.test2.test3.test4.boom", str(cm.exception)) 164 | 165 | def test_call_chain_is_maintained(self): 166 | m = mock.Mock() 167 | m.test1().test2.test3().test4 168 | 169 | mock.seal(m) 170 | with self.assertRaises(AttributeError) as cm: 171 | m.test1().test2.test3().test4() 172 | self.assertIn("mock.test1().test2.test3().test4", str(cm.exception)) 173 | 174 | def test_seal_with_autospec(self): 175 | # https://bugs.python.org/issue45156 176 | class Foo: 177 | foo = 0 178 | def bar1(self): pass 179 | def bar2(self): pass 180 | 181 | class Baz: 182 | baz = 3 183 | def ban(self): pass 184 | 185 | for spec_set in (True, False): 186 | with self.subTest(spec_set=spec_set): 187 | foo = mock.create_autospec(Foo, spec_set=spec_set) 188 | foo.bar1.return_value = 'a' 189 | foo.Baz.ban.return_value = 'b' 190 | 191 | mock.seal(foo) 192 | 193 | self.assertIsInstance(foo.foo, mock.NonCallableMagicMock) 194 | self.assertIsInstance(foo.bar1, mock.MagicMock) 195 | self.assertIsInstance(foo.bar2, mock.MagicMock) 196 | self.assertIsInstance(foo.Baz, mock.MagicMock) 197 | self.assertIsInstance(foo.Baz.baz, mock.NonCallableMagicMock) 198 | self.assertIsInstance(foo.Baz.ban, mock.MagicMock) 199 | 200 | # see gh-91803 201 | self.assertIsInstance(foo.bar2(), mock.MagicMock) 202 | 203 | self.assertEqual(foo.bar1(), 'a') 204 | foo.bar1.return_value = 'new_a' 205 | self.assertEqual(foo.bar1(), 'new_a') 206 | self.assertEqual(foo.Baz.ban(), 'b') 207 | foo.Baz.ban.return_value = 'new_b' 208 | self.assertEqual(foo.Baz.ban(), 'new_b') 209 | 210 | with self.assertRaises(TypeError): 211 | foo.foo() 212 | with self.assertRaises(AttributeError): 213 | foo.bar = 1 214 | with self.assertRaises(AttributeError): 215 | foo.bar2().x 216 | 217 | foo.bar2.return_value = 'bar2' 218 | self.assertEqual(foo.bar2(), 'bar2') 219 | 220 | with self.assertRaises(AttributeError): 221 | foo.missing_attr 222 | with self.assertRaises(AttributeError): 223 | foo.missing_attr = 1 224 | with self.assertRaises(AttributeError): 225 | foo.missing_method() 226 | with self.assertRaises(TypeError): 227 | foo.Baz.baz() 228 | with self.assertRaises(AttributeError): 229 | foo.Baz.missing_attr 230 | with self.assertRaises(AttributeError): 231 | foo.Baz.missing_attr = 1 232 | with self.assertRaises(AttributeError): 233 | foo.Baz.missing_method() 234 | 235 | 236 | if __name__ == "__main__": 237 | unittest.main() 238 | -------------------------------------------------------------------------------- /mock/tests/testsentinel.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import copy 3 | import pickle 4 | from mock import sentinel, DEFAULT 5 | 6 | 7 | class SentinelTest(unittest.TestCase): 8 | 9 | def testSentinels(self): 10 | self.assertEqual(sentinel.whatever, sentinel.whatever, 11 | 'sentinel not stored') 12 | self.assertNotEqual(sentinel.whatever, sentinel.whateverelse, 13 | 'sentinel should be unique') 14 | 15 | 16 | def testSentinelName(self): 17 | self.assertEqual(str(sentinel.whatever), 'sentinel.whatever', 18 | 'sentinel name incorrect') 19 | 20 | 21 | def testDEFAULT(self): 22 | self.assertIs(DEFAULT, sentinel.DEFAULT) 23 | 24 | def testBases(self): 25 | # If this doesn't raise an AttributeError then help(mock) is broken 26 | self.assertRaises(AttributeError, lambda: sentinel.__bases__) 27 | 28 | def testPickle(self): 29 | for proto in range(pickle.HIGHEST_PROTOCOL+1): 30 | with self.subTest(protocol=proto): 31 | pickled = pickle.dumps(sentinel.whatever, proto) 32 | unpickled = pickle.loads(pickled) 33 | self.assertIs(unpickled, sentinel.whatever) 34 | 35 | def testCopy(self): 36 | self.assertIs(copy.copy(sentinel.whatever), sentinel.whatever) 37 | self.assertIs(copy.deepcopy(sentinel.whatever), sentinel.whatever) 38 | 39 | 40 | if __name__ == '__main__': 41 | unittest.main() 42 | -------------------------------------------------------------------------------- /mock/tests/testthreadingmock.py: -------------------------------------------------------------------------------- 1 | import time 2 | import unittest 3 | import concurrent.futures 4 | 5 | from mock import patch, ThreadingMock 6 | 7 | VERY_SHORT_TIMEOUT = 0.1 8 | 9 | 10 | class Something: 11 | def method_1(self): 12 | pass # pragma: no cover 13 | 14 | def method_2(self): 15 | pass # pragma: no cover 16 | 17 | 18 | class TestThreadingMock(unittest.TestCase): 19 | def _call_after_delay(self, func, *args, **kwargs): 20 | time.sleep(kwargs.pop("delay")) 21 | func(*args, **kwargs) 22 | 23 | def setUp(self): 24 | self._executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) 25 | 26 | def tearDown(self): 27 | self._executor.shutdown() 28 | 29 | def run_async(self, func, *args, delay=0, **kwargs): 30 | self._executor.submit( 31 | self._call_after_delay, func, *args, **kwargs, delay=delay 32 | ) 33 | 34 | def _make_mock(self, *args, **kwargs): 35 | return ThreadingMock(*args, **kwargs) 36 | 37 | def test_spec(self): 38 | waitable_mock = self._make_mock(spec=Something) 39 | 40 | with patch(f"{__name__}.Something", waitable_mock) as m: 41 | something = m() 42 | 43 | self.assertIsInstance(something.method_1, ThreadingMock) 44 | self.assertIsInstance(something.method_1().method_2(), ThreadingMock) 45 | 46 | with self.assertRaises(AttributeError): 47 | m.test 48 | 49 | def test_side_effect(self): 50 | waitable_mock = self._make_mock() 51 | 52 | with patch(f"{__name__}.Something", waitable_mock): 53 | something = Something() 54 | something.method_1.side_effect = [1] 55 | 56 | self.assertEqual(something.method_1(), 1) 57 | 58 | def test_instance_check(self): 59 | waitable_mock = self._make_mock() 60 | 61 | with patch(f"{__name__}.Something", waitable_mock): 62 | something = Something() 63 | 64 | self.assertIsInstance(something.method_1, ThreadingMock) 65 | self.assertIsInstance(something.method_1().method_2(), ThreadingMock) 66 | 67 | def test_dynamic_child_mocks_are_threading_mocks(self): 68 | waitable_mock = self._make_mock() 69 | self.assertIsInstance(waitable_mock.child, ThreadingMock) 70 | 71 | def test_dynamic_child_mocks_inherit_timeout(self): 72 | mock1 = self._make_mock() 73 | self.assertIs(mock1._mock_wait_timeout, None) 74 | mock2 = self._make_mock(timeout=2) 75 | self.assertEqual(mock2._mock_wait_timeout, 2) 76 | mock3 = self._make_mock(timeout=3) 77 | self.assertEqual(mock3._mock_wait_timeout, 3) 78 | 79 | self.assertIs(mock1.child._mock_wait_timeout, None) 80 | self.assertEqual(mock2.child._mock_wait_timeout, 2) 81 | self.assertEqual(mock3.child._mock_wait_timeout, 3) 82 | 83 | self.assertEqual(mock2.really().__mul__().complex._mock_wait_timeout, 2) 84 | 85 | def test_no_name_clash(self): 86 | waitable_mock = self._make_mock() 87 | waitable_mock._event = "myevent" 88 | waitable_mock.event = "myevent" 89 | waitable_mock.timeout = "mytimeout" 90 | waitable_mock("works") 91 | waitable_mock.wait_until_called() 92 | waitable_mock.wait_until_any_call_with("works") 93 | 94 | def test_patch(self): 95 | waitable_mock = self._make_mock(spec=Something) 96 | 97 | with patch(f"{__name__}.Something", waitable_mock): 98 | something = Something() 99 | something.method_1() 100 | something.method_1.wait_until_called() 101 | 102 | def test_wait_already_called_success(self): 103 | waitable_mock = self._make_mock(spec=Something) 104 | waitable_mock.method_1() 105 | waitable_mock.method_1.wait_until_called() 106 | waitable_mock.method_1.wait_until_any_call_with() 107 | waitable_mock.method_1.assert_called() 108 | 109 | def test_wait_until_called_success(self): 110 | waitable_mock = self._make_mock(spec=Something) 111 | self.run_async(waitable_mock.method_1, delay=VERY_SHORT_TIMEOUT) 112 | waitable_mock.method_1.wait_until_called() 113 | 114 | def test_wait_until_called_method_timeout(self): 115 | waitable_mock = self._make_mock(spec=Something) 116 | with self.assertRaises(AssertionError): 117 | waitable_mock.method_1.wait_until_called(timeout=VERY_SHORT_TIMEOUT) 118 | 119 | def test_wait_until_called_instance_timeout(self): 120 | waitable_mock = self._make_mock(spec=Something, timeout=VERY_SHORT_TIMEOUT) 121 | with self.assertRaises(AssertionError): 122 | waitable_mock.method_1.wait_until_called() 123 | 124 | def test_wait_until_called_global_timeout(self): 125 | with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"): 126 | ThreadingMock.DEFAULT_TIMEOUT = VERY_SHORT_TIMEOUT 127 | waitable_mock = self._make_mock(spec=Something) 128 | with self.assertRaises(AssertionError): 129 | waitable_mock.method_1.wait_until_called() 130 | 131 | def test_wait_until_any_call_with_success(self): 132 | waitable_mock = self._make_mock() 133 | self.run_async(waitable_mock, delay=VERY_SHORT_TIMEOUT) 134 | waitable_mock.wait_until_any_call_with() 135 | 136 | def test_wait_until_any_call_with_instance_timeout(self): 137 | waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT) 138 | with self.assertRaises(AssertionError): 139 | waitable_mock.wait_until_any_call_with() 140 | 141 | def test_wait_until_any_call_global_timeout(self): 142 | with patch.object(ThreadingMock, "DEFAULT_TIMEOUT"): 143 | ThreadingMock.DEFAULT_TIMEOUT = VERY_SHORT_TIMEOUT 144 | waitable_mock = self._make_mock() 145 | with self.assertRaises(AssertionError): 146 | waitable_mock.wait_until_any_call_with() 147 | 148 | def test_wait_until_any_call_positional(self): 149 | waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT) 150 | waitable_mock.method_1(1, 2, 3) 151 | waitable_mock.method_1.wait_until_any_call_with(1, 2, 3) 152 | with self.assertRaises(AssertionError): 153 | waitable_mock.method_1.wait_until_any_call_with(2, 3, 1) 154 | with self.assertRaises(AssertionError): 155 | waitable_mock.method_1.wait_until_any_call_with() 156 | 157 | def test_wait_until_any_call_kw(self): 158 | waitable_mock = self._make_mock(timeout=VERY_SHORT_TIMEOUT) 159 | waitable_mock.method_1(a=1, b=2) 160 | waitable_mock.method_1.wait_until_any_call_with(a=1, b=2) 161 | with self.assertRaises(AssertionError): 162 | waitable_mock.method_1.wait_until_any_call_with(a=2, b=1) 163 | with self.assertRaises(AssertionError): 164 | waitable_mock.method_1.wait_until_any_call_with() 165 | 166 | def test_magic_methods_success(self): 167 | waitable_mock = self._make_mock() 168 | str(waitable_mock) 169 | waitable_mock.__str__.wait_until_called() 170 | waitable_mock.__str__.assert_called() 171 | 172 | def test_reset_mock_resets_wait(self): 173 | m = self._make_mock(timeout=VERY_SHORT_TIMEOUT) 174 | 175 | with self.assertRaises(AssertionError): 176 | m.wait_until_called() 177 | with self.assertRaises(AssertionError): 178 | m.wait_until_any_call_with() 179 | m() 180 | m.wait_until_called() 181 | m.wait_until_any_call_with() 182 | m.assert_called_once() 183 | 184 | m.reset_mock() 185 | 186 | with self.assertRaises(AssertionError): 187 | m.wait_until_called() 188 | with self.assertRaises(AssertionError): 189 | m.wait_until_any_call_with() 190 | m() 191 | m.wait_until_called() 192 | m.wait_until_any_call_with() 193 | m.assert_called_once() 194 | 195 | 196 | if __name__ == "__main__": 197 | unittest.main() 198 | -------------------------------------------------------------------------------- /mock/tests/testwith.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from warnings import catch_warnings 3 | 4 | from mock.tests.support import is_instance 5 | from mock import MagicMock, Mock, patch, sentinel, mock_open, call 6 | 7 | 8 | 9 | something = sentinel.Something 10 | something_else = sentinel.SomethingElse 11 | 12 | 13 | class SampleException(Exception): pass 14 | 15 | 16 | class WithTest(unittest.TestCase): 17 | 18 | def test_with_statement(self): 19 | with patch('%s.something' % __name__, sentinel.Something2): 20 | self.assertEqual(something, sentinel.Something2, "unpatched") 21 | self.assertEqual(something, sentinel.Something) 22 | 23 | 24 | def test_with_statement_exception(self): 25 | with self.assertRaises(SampleException): 26 | with patch('%s.something' % __name__, sentinel.Something2): 27 | self.assertEqual(something, sentinel.Something2, "unpatched") 28 | raise SampleException() 29 | self.assertEqual(something, sentinel.Something) 30 | 31 | 32 | def test_with_statement_as(self): 33 | with patch('%s.something' % __name__) as mock_something: 34 | self.assertEqual(something, mock_something, "unpatched") 35 | self.assertTrue(is_instance(mock_something, MagicMock), 36 | "patching wrong type") 37 | self.assertEqual(something, sentinel.Something) 38 | 39 | 40 | def test_patch_object_with_statement(self): 41 | class Foo(object): 42 | something = 'foo' 43 | original = Foo.something 44 | with patch.object(Foo, 'something'): 45 | self.assertNotEqual(Foo.something, original, "unpatched") 46 | self.assertEqual(Foo.something, original) 47 | 48 | 49 | def test_with_statement_nested(self): 50 | with catch_warnings(record=True): 51 | with patch('%s.something' % __name__) as mock_something, patch('%s.something_else' % __name__) as mock_something_else: 52 | self.assertEqual(something, mock_something, "unpatched") 53 | self.assertEqual(something_else, mock_something_else, 54 | "unpatched") 55 | 56 | self.assertEqual(something, sentinel.Something) 57 | self.assertEqual(something_else, sentinel.SomethingElse) 58 | 59 | 60 | def test_with_statement_specified(self): 61 | with patch('%s.something' % __name__, sentinel.Patched) as mock_something: 62 | self.assertEqual(something, mock_something, "unpatched") 63 | self.assertEqual(mock_something, sentinel.Patched, "wrong patch") 64 | self.assertEqual(something, sentinel.Something) 65 | 66 | 67 | def testContextManagerMocking(self): 68 | mock = Mock() 69 | mock.__enter__ = Mock() 70 | mock.__exit__ = Mock() 71 | mock.__exit__.return_value = False 72 | 73 | with mock as m: 74 | self.assertEqual(m, mock.__enter__.return_value) 75 | mock.__enter__.assert_called_with() 76 | mock.__exit__.assert_called_with(None, None, None) 77 | 78 | 79 | def test_context_manager_with_magic_mock(self): 80 | mock = MagicMock() 81 | 82 | with self.assertRaises(TypeError): 83 | with mock: 84 | 'foo' + 3 85 | mock.__enter__.assert_called_with() 86 | self.assertTrue(mock.__exit__.called) 87 | 88 | 89 | def test_with_statement_same_attribute(self): 90 | with patch('%s.something' % __name__, sentinel.Patched) as mock_something: 91 | self.assertEqual(something, mock_something, "unpatched") 92 | 93 | with patch('%s.something' % __name__) as mock_again: 94 | self.assertEqual(something, mock_again, "unpatched") 95 | 96 | self.assertEqual(something, mock_something, 97 | "restored with wrong instance") 98 | 99 | self.assertEqual(something, sentinel.Something, "not restored") 100 | 101 | 102 | def test_with_statement_imbricated(self): 103 | with patch('%s.something' % __name__) as mock_something: 104 | self.assertEqual(something, mock_something, "unpatched") 105 | 106 | with patch('%s.something_else' % __name__) as mock_something_else: 107 | self.assertEqual(something_else, mock_something_else, 108 | "unpatched") 109 | 110 | self.assertEqual(something, sentinel.Something) 111 | self.assertEqual(something_else, sentinel.SomethingElse) 112 | 113 | 114 | def test_dict_context_manager(self): 115 | foo = {} 116 | with patch.dict(foo, {'a': 'b'}): 117 | self.assertEqual(foo, {'a': 'b'}) 118 | self.assertEqual(foo, {}) 119 | 120 | with self.assertRaises(NameError): 121 | with patch.dict(foo, {'a': 'b'}): 122 | self.assertEqual(foo, {'a': 'b'}) 123 | raise NameError('Konrad') 124 | 125 | self.assertEqual(foo, {}) 126 | 127 | def test_double_patch_instance_method(self): 128 | class C: 129 | def f(self): pass 130 | 131 | c = C() 132 | 133 | with patch.object(c, 'f') as patch1: 134 | with patch.object(c, 'f') as patch2: 135 | c.f() 136 | self.assertEqual(patch2.call_count, 1) 137 | self.assertEqual(patch1.call_count, 0) 138 | c.f() 139 | self.assertEqual(patch1.call_count, 1) 140 | 141 | 142 | class TestMockOpen(unittest.TestCase): 143 | 144 | def test_mock_open(self): 145 | mock = mock_open() 146 | with patch('%s.open' % __name__, mock, create=True) as patched: 147 | self.assertIs(patched, mock) 148 | open('foo') 149 | 150 | mock.assert_called_once_with('foo') 151 | 152 | 153 | def test_mock_open_context_manager(self): 154 | mock = mock_open() 155 | handle = mock.return_value 156 | with patch('%s.open' % __name__, mock, create=True): 157 | with open('foo') as f: 158 | f.read() 159 | 160 | expected_calls = [call('foo'), call().__enter__(), call().read(), 161 | call().__exit__(None, None, None), call().close()] 162 | self.assertEqual(mock.mock_calls, expected_calls) 163 | self.assertIs(f, handle) 164 | 165 | def test_mock_open_context_manager_multiple_times(self): 166 | mock = mock_open() 167 | with patch('%s.open' % __name__, mock, create=True): 168 | with open('foo') as f: 169 | f.read() 170 | with open('bar') as f: 171 | f.read() 172 | 173 | expected_calls = [ 174 | call('foo'), call().__enter__(), call().read(), 175 | call().__exit__(None, None, None), call().close(), 176 | call('bar'), call().__enter__(), call().read(), 177 | call().__exit__(None, None, None), call().close()] 178 | self.assertEqual(mock.mock_calls, expected_calls) 179 | 180 | def test_explicit_mock(self): 181 | mock = MagicMock() 182 | mock_open(mock) 183 | 184 | with patch('%s.open' % __name__, mock, create=True) as patched: 185 | self.assertIs(patched, mock) 186 | open('foo') 187 | 188 | mock.assert_called_once_with('foo') 189 | 190 | 191 | def test_read_data(self): 192 | mock = mock_open(read_data='foo') 193 | with patch('%s.open' % __name__, mock, create=True): 194 | h = open('bar') 195 | result = h.read() 196 | 197 | self.assertEqual(result, 'foo') 198 | 199 | 200 | def test_readline_data(self): 201 | # Check that readline will return all the lines from the fake file 202 | # And that once fully consumed, readline will return an empty string. 203 | mock = mock_open(read_data='foo\nbar\nbaz\n') 204 | with patch('%s.open' % __name__, mock, create=True): 205 | h = open('bar') 206 | line1 = h.readline() 207 | line2 = h.readline() 208 | line3 = h.readline() 209 | self.assertEqual(line1, 'foo\n') 210 | self.assertEqual(line2, 'bar\n') 211 | self.assertEqual(line3, 'baz\n') 212 | self.assertEqual(h.readline(), '') 213 | 214 | # Check that we properly emulate a file that doesn't end in a newline 215 | mock = mock_open(read_data='foo') 216 | with patch('%s.open' % __name__, mock, create=True): 217 | h = open('bar') 218 | result = h.readline() 219 | self.assertEqual(result, 'foo') 220 | self.assertEqual(h.readline(), '') 221 | 222 | 223 | def test_dunder_iter_data(self): 224 | # Check that dunder_iter will return all the lines from the fake file. 225 | mock = mock_open(read_data='foo\nbar\nbaz\n') 226 | with patch('%s.open' % __name__, mock, create=True): 227 | h = open('bar') 228 | lines = [l for l in h] 229 | self.assertEqual(lines[0], 'foo\n') 230 | self.assertEqual(lines[1], 'bar\n') 231 | self.assertEqual(lines[2], 'baz\n') 232 | self.assertEqual(h.readline(), '') 233 | with self.assertRaises(StopIteration): 234 | next(h) 235 | 236 | def test_next_data(self): 237 | # Check that next will correctly return the next available 238 | # line and plays well with the dunder_iter part. 239 | mock = mock_open(read_data='foo\nbar\nbaz\n') 240 | with patch('%s.open' % __name__, mock, create=True): 241 | h = open('bar') 242 | line1 = next(h) 243 | line2 = next(h) 244 | lines = [l for l in h] 245 | self.assertEqual(line1, 'foo\n') 246 | self.assertEqual(line2, 'bar\n') 247 | self.assertEqual(lines[0], 'baz\n') 248 | self.assertEqual(h.readline(), '') 249 | 250 | def test_readlines_data(self): 251 | # Test that emulating a file that ends in a newline character works 252 | mock = mock_open(read_data='foo\nbar\nbaz\n') 253 | with patch('%s.open' % __name__, mock, create=True): 254 | h = open('bar') 255 | result = h.readlines() 256 | self.assertEqual(result, ['foo\n', 'bar\n', 'baz\n']) 257 | 258 | # Test that files without a final newline will also be correctly 259 | # emulated 260 | mock = mock_open(read_data='foo\nbar\nbaz') 261 | with patch('%s.open' % __name__, mock, create=True): 262 | h = open('bar') 263 | result = h.readlines() 264 | 265 | self.assertEqual(result, ['foo\n', 'bar\n', 'baz']) 266 | 267 | 268 | def test_read_bytes(self): 269 | mock = mock_open(read_data=b'\xc6') 270 | with patch('%s.open' % __name__, mock, create=True): 271 | with open('abc', 'rb') as f: 272 | result = f.read() 273 | self.assertEqual(result, b'\xc6') 274 | 275 | 276 | def test_readline_bytes(self): 277 | m = mock_open(read_data=b'abc\ndef\nghi\n') 278 | with patch('%s.open' % __name__, m, create=True): 279 | with open('abc', 'rb') as f: 280 | line1 = f.readline() 281 | line2 = f.readline() 282 | line3 = f.readline() 283 | self.assertEqual(line1, b'abc\n') 284 | self.assertEqual(line2, b'def\n') 285 | self.assertEqual(line3, b'ghi\n') 286 | 287 | 288 | def test_readlines_bytes(self): 289 | m = mock_open(read_data=b'abc\ndef\nghi\n') 290 | with patch('%s.open' % __name__, m, create=True): 291 | with open('abc', 'rb') as f: 292 | result = f.readlines() 293 | self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n']) 294 | 295 | 296 | def test_mock_open_read_with_argument(self): 297 | # At one point calling read with an argument was broken 298 | # for mocks returned by mock_open 299 | some_data = 'foo\nbar\nbaz' 300 | mock = mock_open(read_data=some_data) 301 | self.assertEqual(mock().read(10), some_data[:10]) 302 | self.assertEqual(mock().read(10), some_data[:10]) 303 | 304 | f = mock() 305 | self.assertEqual(f.read(10), some_data[:10]) 306 | self.assertEqual(f.read(10), some_data[10:]) 307 | 308 | 309 | def test_interleaved_reads(self): 310 | # Test that calling read, readline, and readlines pulls data 311 | # sequentially from the data we preload with 312 | mock = mock_open(read_data='foo\nbar\nbaz\n') 313 | with patch('%s.open' % __name__, mock, create=True): 314 | h = open('bar') 315 | line1 = h.readline() 316 | rest = h.readlines() 317 | self.assertEqual(line1, 'foo\n') 318 | self.assertEqual(rest, ['bar\n', 'baz\n']) 319 | 320 | mock = mock_open(read_data='foo\nbar\nbaz\n') 321 | with patch('%s.open' % __name__, mock, create=True): 322 | h = open('bar') 323 | line1 = h.readline() 324 | rest = h.read() 325 | self.assertEqual(line1, 'foo\n') 326 | self.assertEqual(rest, 'bar\nbaz\n') 327 | 328 | 329 | def test_overriding_return_values(self): 330 | mock = mock_open(read_data='foo') 331 | handle = mock() 332 | 333 | handle.read.return_value = 'bar' 334 | handle.readline.return_value = 'bar' 335 | handle.readlines.return_value = ['bar'] 336 | 337 | self.assertEqual(handle.read(), 'bar') 338 | self.assertEqual(handle.readline(), 'bar') 339 | self.assertEqual(handle.readlines(), ['bar']) 340 | 341 | # call repeatedly to check that a StopIteration is not propagated 342 | self.assertEqual(handle.readline(), 'bar') 343 | self.assertEqual(handle.readline(), 'bar') 344 | 345 | 346 | if __name__ == '__main__': 347 | unittest.main() 348 | -------------------------------------------------------------------------------- /release.py: -------------------------------------------------------------------------------- 1 | import re 2 | from glob import glob 3 | from os.path import join 4 | from subprocess import call 5 | 6 | import blurb as blurb_module 7 | from argparse import ArgumentParser 8 | from mock import version_info 9 | 10 | VERSION_TYPES = ['major', 'minor', 'bugfix'] 11 | 12 | 13 | def incremented_version(version_info, type_): 14 | type_index = VERSION_TYPES.index(type_) 15 | version_info = tuple(0 if i>type_index else (e+(1 if i==type_index else 0)) 16 | for i, e in enumerate(version_info)) 17 | return '.'.join(str(p) for p in version_info) 18 | 19 | 20 | def text_from_news(): 21 | # hack: 22 | blurb_module.sections.append('NEWS.d') 23 | 24 | blurbs = blurb_module.Blurbs() 25 | for path in glob(join('NEWS.d', '*')): 26 | blurbs.load_next(path) 27 | 28 | text = [] 29 | for metadata, body in blurbs: 30 | bpo = metadata.get('bpo') 31 | gh = metadata.get('gh-issue') 32 | issue = f'bpo-{bpo}' if bpo else f'gh-{gh}' 33 | body = f"- {issue}: " + body 34 | text.append(blurb_module.textwrap_body(body, subsequent_indent=' ')) 35 | 36 | return '\n'.join(text) 37 | 38 | 39 | def news_to_changelog(version): 40 | with open('CHANGELOG.rst') as source: 41 | current_changelog = source.read() 42 | 43 | text = [version] 44 | text.append('-'*len(version)) 45 | text.append('') 46 | text.append(text_from_news()) 47 | text.append(current_changelog) 48 | 49 | new_changelog = '\n'.join(text) 50 | with open('CHANGELOG.rst', 'w') as target: 51 | target.write(new_changelog) 52 | 53 | 54 | def update_version(new_version): 55 | path = join('mock', '__init__.py') 56 | with open(path) as source: 57 | text = source.read() 58 | 59 | text = re.sub("(__version__ = ')[^']+(')", 60 | r"\g<1>"+new_version+r"\2", 61 | text) 62 | 63 | with open(path, 'w') as target: 64 | target.write(text) 65 | 66 | 67 | def git(command): 68 | return call('git '+command, shell=True) 69 | 70 | 71 | def git_commit(new_version): 72 | git('rm NEWS.d/*') 73 | git('add CHANGELOG.rst') 74 | git('add mock/__init__.py') 75 | git(f'commit -m "Preparing for {new_version} release."') 76 | 77 | 78 | def parse_args(): 79 | parser = ArgumentParser() 80 | parser.add_argument('type', choices=VERSION_TYPES) 81 | return parser.parse_args() 82 | 83 | 84 | def main(): 85 | args = parse_args() 86 | new_version = incremented_version(version_info, args.type) 87 | news_to_changelog(new_version) 88 | update_version(new_version) 89 | git_commit(new_version) 90 | print(f'{new_version} ready to push, please check the HEAD commit first!') 91 | 92 | 93 | if __name__ == '__main__': 94 | main() 95 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = mock 3 | summary = Rolling backport of unittest.mock for all Pythons 4 | home-page = http://mock.readthedocs.org/en/latest/ 5 | description-file = README.rst 6 | author = Testing Cabal 7 | author-email = testing-in-python@lists.idyll.org 8 | classifiers = 9 | Development Status :: 5 - Production/Stable 10 | Environment :: Console 11 | Intended Audience :: Developers 12 | License :: OSI Approved :: BSD License 13 | Operating System :: OS Independent 14 | Programming Language :: Python 15 | Programming Language :: Python :: 3.6 16 | Programming Language :: Python :: 3.7 17 | Programming Language :: Python :: 3.8 18 | Programming Language :: Python :: 3.9 19 | Programming Language :: Python :: 3.10 20 | Programming Language :: Python :: 3.11 21 | Programming Language :: Python :: 3.12 22 | Programming Language :: Python :: 3.13 23 | Programming Language :: Python :: Implementation :: CPython 24 | Programming Language :: Python :: Implementation :: PyPy 25 | Topic :: Software Development :: Libraries 26 | Topic :: Software Development :: Libraries :: Python Modules 27 | Topic :: Software Development :: Testing 28 | project_urls = 29 | Source = https://github.com/testing-cabal/mock 30 | keyword = 31 | testing, test, mock, mocking, unittest, patching, stubs, fakes, doubles 32 | 33 | [options] 34 | python_requires=>=3.6 35 | packages = mock 36 | 37 | [options.extras_require] 38 | docs = 39 | sphinx 40 | test = 41 | pytest 42 | pytest-cov 43 | build = 44 | twine 45 | wheel 46 | blurb 47 | 48 | [tool:pytest] 49 | python_files=test*.py 50 | filterwarnings = 51 | error::RuntimeWarning 52 | ignore::DeprecationWarning 53 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import re 2 | from os.path import join 3 | 4 | import setuptools 5 | 6 | setuptools.setup( 7 | version=re.search("__version__ = '([^']+)'", 8 | open(join('mock', '__init__.py')).read()).group(1), 9 | long_description=open('README.rst').read(), 10 | ) 11 | --------------------------------------------------------------------------------