pax_global_header00006660000000000000000000000064137643472230014525gustar00rootroot0000000000000052 comment=93cf533a95abc697ad36c8d1ddef82058b884425 mock-4.0.3/000077500000000000000000000000001376434722300124625ustar00rootroot00000000000000mock-4.0.3/.carthorse.yml000066400000000000000000000003461376434722300152600ustar00rootroot00000000000000carthorse: version-from: setup.py tag-format: "{version}" when: - version-not-tagged actions: - run: "sudo pip install -e .[build]" - run: "twine upload -u carthorse-mock -p $PYPI_PASS dist/*" - create-tag mock-4.0.3/.circleci/000077500000000000000000000000001376434722300143155ustar00rootroot00000000000000mock-4.0.3/.circleci/config.yml000066400000000000000000000041411376434722300163050ustar00rootroot00000000000000version: 2.1 orbs: python: cjw296/python-ci@2 jobs: check-package: parameters: image: type: string python: type: string default: "python" docker: - image: << parameters.image >> steps: - python/check-package: package: "mock" test: - run: name: "Import package" command: << parameters.python >> -c "import mock" common: &common jobs: - python/pip-run-tests: name: python36 image: circleci/python:3.6 - python/pip-run-tests: name: python37 image: circleci/python:3.7 - python/pip-run-tests: name: python38 image: circleci/python:3.8 - python/pip-run-tests: name: pypy36 image: pypy:3.6 - python/coverage: name: coverage requires: - python36 - python37 - python38 - pypy36 - python/pip-docs: name: docs requires: - coverage - python/pip-setuptools-build-package: name: package requires: - docs filters: branches: only: master - check-package: name: check-package-python36 image: circleci/python:3.6 requires: - package - check-package: name: check-package-python37 image: circleci/python:3.7 requires: - package - check-package: name: check-package-python38 image: circleci/python:3.8 requires: - package - check-package: name: check-package-pypy36 image: pypy:3.6 python: pypy3 requires: - package - python/release: name: release config: .carthorse.yml requires: - check-package-python36 - check-package-python37 - check-package-python38 - check-package-pypy36 workflows: push: <<: *common periodic: <<: *common triggers: - schedule: cron: "0 1 * * *" filters: branches: only: master mock-4.0.3/.coveragerc000066400000000000000000000002551376434722300146050ustar00rootroot00000000000000[run] source = mock [report] exclude_lines = pragma: no cover if __name__ == .__main__.: : pass : yield [paths] source = mock/ /root/project/mock/ mock-4.0.3/.github/000077500000000000000000000000001376434722300140225ustar00rootroot00000000000000mock-4.0.3/.github/ISSUE_TEMPLATE/000077500000000000000000000000001376434722300162055ustar00rootroot00000000000000mock-4.0.3/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000021671376434722300207050ustar00rootroot00000000000000--- name: Bug report about: Only report bugs here that are specific to this backport. title: '' labels: '' assignees: '' --- This package is a rolling backport of [`unittest.mock`](https://github.com/python/cpython/blob/master/Lib/unittest/mock.py). As such, any problems you encounter most likely need to be fixed upstream. 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`. If the issue still occurs, then please report upstream through https://bugs.python.org/ as it will need to be fixed there so that it can be backported here and released to you. 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: **What versions are you using?** - Python: [e.g. 3.7.1] - Mock: [e.g. 4.0.2] - Operating System: [e.g.Linux, macOS, Windows] **What happened?** **What were you hoping to happen instead?** mock-4.0.3/.gitignore000066400000000000000000000002271376434722300144530ustar00rootroot00000000000000.*\.pyc html/ mock\.egg-info/ mock\.wpu \.tox/ build dist latex .*\$py\.class runtox *~ *.pyc .testrepository .*.swp README.html .coverage .coverage.* mock-4.0.3/.readthedocs.yml000066400000000000000000000001661376434722300155530ustar00rootroot00000000000000version: 2 python: version: 3.7 install: - method: pip path: . extra_requirements: - docs mock-4.0.3/CHANGELOG.rst000066400000000000000000000321311376434722300145030ustar00rootroot000000000000004.0.3 ----- - Issue #42532: Remove unexpected call of ``__bool__`` when passing a ``spec_arg`` argument to a Mock. - Issue #39966: Revert bpo-25597. :class:`unittest.mock.MagicMock` with wraps' set uses default return values for magic methods. - Issue #41877: Mock objects which are not unsafe will now raise an AttributeError if an attribute with the prefix asert, aseert, or assrt is accessed, in addition to this already happening for the prefixes assert or assret. - Issue #40126: Fixed reverting multiple patches in unittest.mock. Patcher's ``__exit__()`` is now never called if its ``__enter__()`` is failed. Returning true from ``__exit__()`` silences now the exception. 4.0.2 ----- - Issue #39915: Ensure :attr:`unittest.mock.AsyncMock.await_args_list` has call objects in the order of awaited arguments instead of using :attr:`unittest.mock.Mock.call_args` which has the last value of the call. Patch by Karthikeyan Singaravelan. 4.0.1 ----- - Remove the universal marker from the wheel. 4.0.0 ----- - No Changes from 4.0.0b1. 4.0.0b1 ------- - The release is a fresh cut of cpython's `4a686504`__. All changes to :mod:`mock` from that commit and before are included in this release along with the subsequent changes listed below. __ https://github.com/python/cpython/commit/4a686504eb2bbf69adf78077458508a7ba131667 - Issue #37972: Subscripts to the `unittest.mock.call` objects now receive the same chaining mechanism as any other custom attributes, so that the following usage no longer raises a `TypeError`: call().foo().__getitem__('bar') Patch by blhsing - Issue #38839: Fix some unused functions in tests. Patch by Adam Johnson. - Issue #39485: Fix a bug in :func:`unittest.mock.create_autospec` that would complain about the wrong number of arguments for custom descriptors defined in an extension module returning functions. - Issue #39082: Allow AsyncMock to correctly patch static/class methods - Issue #38093: Fixes AsyncMock so it doesn't crash when used with AsyncContextManagers or AsyncIterators. - Issue #38859: AsyncMock now returns StopAsyncIteration on the exaustion of a side_effects iterable. Since PEP-479 its Impossible to raise a StopIteration exception from a coroutine. - Issue #38163: Child mocks will now detect their type as either synchronous or asynchronous, asynchronous child mocks will be AsyncMocks and synchronous child mocks will be either MagicMock or Mock (depending on their parent type). - Issue #38473: Use signature from inner mock for autospecced methods attached with :func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan. - Issue #38136: Changes AsyncMock call count and await count to be two different counters. Now await count only counts when a coroutine has been awaited, not when it has been called, and vice-versa. Update the documentation around this. - Issue #37555: Fix `NonCallableMock._call_matcher` returning tuple instead of `_Call` object when `self._spec_signature` exists. Patch by Elizabeth Uselton - Issue #37251: Remove `__code__` check in AsyncMock that incorrectly evaluated function specs as async objects but failed to evaluate classes with `__await__` but no `__code__` attribute defined as async objects. - Issue #38669: Raise :exc:`TypeError` when passing target as a string with :meth:`unittest.mock.patch.object`. - Issue #25597: Ensure, if ``wraps`` is supplied to :class:`unittest.mock.MagicMock`, it is used to calculate return values for the magic methods instead of using the default return values. Patch by Karthikeyan Singaravelan. - Issue #38108: Any synchronous magic methods on an AsyncMock now return a MagicMock. Any asynchronous magic methods on a MagicMock now return an AsyncMock. - Issue #21478: Record calls to parent when autospecced object is attached to a mock using :func:`unittest.mock.attach_mock`. Patch by Karthikeyan Singaravelan. - Issue #38857: AsyncMock fix for return values that are awaitable types. This also covers side_effect iterable values that happend to be awaitable, and wraps callables that return an awaitable type. Before these awaitables were being awaited instead of being returned as is. - Issue #38932: Mock fully resets child objects on reset_mock(). Patch by Vegard Stikbakke - Issue #37685: Fixed ``__eq__``, ``__lt__`` etc implementations in some classes. They now return :data:`NotImplemented` for unsupported type of the other operand. This allows the other operand to play role (for example the equality comparison with :data:`~unittest.mock.ANY` will return ``True``). - Issue #37212: :func:`unittest.mock.call` now preserves the order of keyword arguments in repr output. Patch by Karthikeyan Singaravelan. - Issue #37828: Fix default mock name in :meth:`unittest.mock.Mock.assert_called` exceptions. Patch by Abraham Toriz Cruz. - Issue #36871: Improve error handling for the assert_has_calls and assert_has_awaits methods of mocks. Fixed a bug where any errors encountered while binding the expected calls to the mock's spec were silently swallowed, leading to misleading error output. - Issue #21600: Fix :func:`mock.patch.stopall` to stop active patches that were created with :func:`mock.patch.dict`. - Issue #38161: Removes _AwaitEvent from AsyncMock. - Issue #36871: Ensure method signature is used instead of constructor signature of a class while asserting mock object against method calls. Patch by Karthikeyan Singaravelan. 3.0.5 ----- - Issue #31855: :func:`unittest.mock.mock_open` results now respects the argument of read([size]). Patch contributed by Rémi Lapeyre. 3.0.4 ----- - Include the license, readme and changelog in the source distribution. 3.0.3 ----- - Fixed patching of dictionaries, when specifying the target with a unicode on Python 2. 3.0.2 ----- - Add missing ``funcsigs`` dependency on Python 2. 3.0.1 ----- - Fix packaging issue where ``six`` was missed as a dependency. 3.0.0 ----- - Issue #35226: Recursively check arguments when testing for equality of :class:`unittest.mock.call` objects and add note that tracking of parameters used to create ancestors of mocks in ``mock_calls`` is not possible. - Issue #31177: Fix bug that prevented using :meth:`reset_mock ` on mock instances with deleted attributes - Issue #26704: Added test demonstrating double-patching of an instance method. Patch by Anthony Sottile. - Issue #35500: Write expected and actual call parameters on separate lines in :meth:`unittest.mock.Mock.assert_called_with` assertion errors. Contributed by Susan Su. - Issue #35330: When a :class:`Mock` instance was used to wrap an object, if `side_effect` is used in one of the mocks of it methods, don't call the original implementation and return the result of using the side effect the same way that it is done with return_value. - Issue #30541: Add new function to seal a mock and prevent the automatically creation of child mocks. Patch by Mario Corchero. - Issue #35022: :class:`unittest.mock.MagicMock` now supports the ``__fspath__`` method (from :class:`os.PathLike`). - Issue #33516: :class:`unittest.mock.MagicMock` now supports the ``__round__`` magic method. - Issue #35512: :func:`unittest.mock.patch.dict` used as a decorator with string target resolves the target during function call instead of during decorator construction. Patch by Karthikeyan Singaravelan. - Issue #36366: Calling ``stop()`` on an unstarted or stopped :func:`unittest.mock.patch` object will now return `None` instead of raising :exc:`RuntimeError`, making the method idempotent. Patch byKarthikeyan Singaravelan. - Issue #35357: Internal attributes' names of unittest.mock._Call and unittest.mock.MagicProxy (name, parent & from_kall) are now prefixed with _mock_ in order to prevent clashes with widely used object attributes. Fixed minor typo in test function name. - Issue #20239: Allow repeated assignment deletion of :class:`unittest.mock.Mock` attributes. Patch by Pablo Galindo. - Issue #35082: Don't return deleted attributes when calling dir on a :class:`unittest.mock.Mock`. - Issue #0: Improved an error message when mock assert_has_calls fails. - Issue #23078: Add support for :func:`classmethod` and :func:`staticmethod` to :func:`unittest.mock.create_autospec`. Initial patch by Felipe Ochoa. - Issue #21478: Calls to a child function created with :func:`unittest.mock.create_autospec` should propagate to the parent. Patch by Karthikeyan Singaravelan. - Issue #36598: Fix ``isinstance`` check for Mock objects with spec when the code is executed under tracing. Patch by Karthikeyan Singaravelan. - Issue #32933: :func:`unittest.mock.mock_open` now supports iteration over the file contents. Patch by Tony Flury. - Issue #21269: Add ``args`` and ``kwargs`` properties to mock call objects. Contributed by Kumar Akshay. - Issue #17185: Set ``__signature__`` on mock for :mod:`inspect` to get signature. Patch by Karthikeyan Singaravelan. - Issue #35047: ``unittest.mock`` now includes mock calls in exception messages if ``assert_not_called``, ``assert_called_once``, or ``assert_called_once_with`` fails. Patch by Petter Strandmark. - Issue #28380: unittest.mock Mock autospec functions now properly support assert_called, assert_not_called, and assert_called_once. - Issue #28735: Fixed the comparison of mock.MagickMock with mock.ANY. - Issue #20804: The unittest.mock.sentinel attributes now preserve their identity when they are copied or pickled. - Issue #28961: Fix unittest.mock._Call helper: don't ignore the name parameter anymore. Patch written by Jiajun Huang. - Issue #26750: unittest.mock.create_autospec() now works properly for subclasses of property() and other data descriptors. - Issue #21271: New keyword only parameters in reset_mock call. - Issue #26807: mock_open 'files' no longer error on readline at end of file. Patch from Yolanda Robla. - Issue #25195: Fix a regression in mock.MagicMock. _Call is a subclass of tuple (changeset 3603bae63c13 only works for classes) so we need to implement __ne__ ourselves. Patch by Andrew Plummer. 2.0.0 and earlier ----------------- - Issue #26323: Add Mock.assert_called() and Mock.assert_called_once() methods to unittest.mock. Patch written by Amit Saha. - Issue #22138: Fix mock.patch behavior when patching descriptors. Restore original values after patching. Patch contributed by Sean McCully. - Issue #24857: Comparing call_args to a long sequence now correctly returns a boolean result instead of raising an exception. Patch by A Kaptur. - Issue #23004: mock_open() now reads binary data correctly when the type of read_data is bytes. Initial patch by Aaron Hill. - Issue #21750: mock_open.read_data can now be read from each instance, as it could in Python 3.3. - Issue #18622: unittest.mock.mock_open().reset_mock would recurse infinitely. Patch from Nicola Palumbo and Laurent De Buyst. - Issue #23661: unittest.mock side_effects can now be exceptions again. This was a regression vs Python 3.4. Patch from Ignacio Rossi - Issue #23310: Fix MagicMock's initializer to work with __methods__, just like configure_mock(). Patch by Kasia Jachim. - Issue #23568: Add rdivmod support to MagicMock() objects. Patch by Håkan Lövdahl. - Issue #23581: Add matmul support to MagicMock. Patch by Håkan Lövdahl. - Issue #23326: Removed __ne__ implementations. Since fixing default __ne__ implementation in issue #21408 they are redundant. *** NOT BACKPORTED *** - Issue #21270: We now override tuple methods in mock.call objects so that they can be used as normal call attributes. - Issue #21256: Printout of keyword args should be in deterministic order in a mock function call. This will help to write better doctests. - Issue #21262: New method assert_not_called for Mock. It raises AssertionError if the mock has been called. - Issue #21238: New keyword argument `unsafe` to Mock. It raises `AttributeError` incase of an attribute startswith assert or assret. - Issue #21239: patch.stopall() didn't work deterministically when the same name was patched more than once. - Issue #21222: Passing name keyword argument to mock.create_autospec now works. - Issue #17826: setting an iterable side_effect on a mock function created by create_autospec now works. Patch by Kushal Das. - Issue #17826: setting an iterable side_effect on a mock function created by create_autospec now works. Patch by Kushal Das. - Issue #20968: unittest.mock.MagicMock now supports division. Patch by Johannes Baiter. - Issue #20189: unittest.mock now no longer assumes that any object for which it could get an inspect.Signature is a callable written in Python. Fix courtesy of Michael Foord. - Issue #17467: add readline and readlines support to mock_open in unittest.mock. - Issue #17015: When it has a spec, a Mock object now inspects its signature when matching calls, so that arguments can be matched positionally or by name. - Issue #15323: improve failure message of Mock.assert_called_once_with - Issue #14857: fix regression in references to PEP 3135 implicit __class__ closure variable (Reopens issue #12370) - Issue #14295: Add unittest.mock mock-4.0.3/LICENSE.txt000066400000000000000000000024761376434722300143160ustar00rootroot00000000000000Copyright (c) 2003-2013, Michael Foord & the mock team All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. mock-4.0.3/MANIFEST.in000066400000000000000000000001041376434722300142130ustar00rootroot00000000000000include LICENSE.txt include *.rst recursive-include mock/tests *.py mock-4.0.3/README.rst000066400000000000000000000027031376434722300141530ustar00rootroot00000000000000mock is a library for testing in Python. It allows you to replace parts of your system under test with mock objects and make assertions about how they have been used. mock is now part of the Python standard library, available as `unittest.mock `_ in Python 3.3 onwards. This package contains a rolling backport of the standard library mock code compatible with Python 3.6 and up. Please see the standard library documentation for more details. :Homepage: `Mock Homepage`_ :Download: `Mock on PyPI`_ :Documentation: `Python Docs`_ :License: `BSD License`_ :Support: `Mailing list (testing-in-python@lists.idyll.org) `_ :Code: `GitHub `_ :Issue tracker: `GitHub Issues `_ :Build status: |CircleCI|_ |Docs|_ .. |CircleCI| image:: https://circleci.com/gh/testing-cabal/mock/tree/master.svg?style=shield .. _CircleCI: https://circleci.com/gh/testing-cabal/mock/tree/master .. |Docs| image:: https://readthedocs.org/projects/mock/badge/?version=latest .. _Docs: http://mock.readthedocs.org/en/latest/ .. _Mock Homepage: http://mock.readthedocs.org/en/latest/ .. _BSD License: https://github.com/testing-cabal/mock/blob/master/LICENSE.txt .. _Python Docs: https://docs.python.org/dev/library/unittest.mock.html .. _mock on PyPI: https://pypi.org/project/mock/ mock-4.0.3/backport.py000066400000000000000000000103371376434722300146450ustar00rootroot00000000000000import re from argparse import ArgumentParser from os.path import dirname, abspath, join from subprocess import check_output, call def git(command, repo): return check_output('git '+command, cwd=repo, shell=True).decode() def repo_state_bad(mock_repo): status = git('status', mock_repo) if 'You are in the middle of an am session' in status: print(f'Mock repo at {mock_repo} needs cleanup:\n') call('git status', shell=True) return True def cleanup_old_patches(mock_repo): print('cleaning up old patches:') call('rm -vf /tmp/*.mock.patch', shell=True) call('find . -name "*.rej" -print -delete', shell=True, cwd=mock_repo) def find_initial_cpython_rev(): with open('lastsync.txt') as source: return source.read().strip() def cpython_revs_affecting_mock(cpython_repo, start): revs = git(f'log --no-merges --format=%H {start}.. ' f'-- Lib/unittest/mock.py Lib/unittest/test/testmock/', repo=cpython_repo).split() revs.reverse() print(f'{len(revs)} patches that may need backporting') return revs def has_been_backported(mock_repo, cpython_rev): backport_rev = git(f'log --format=%H --grep "Backports: {cpython_rev}"', repo=mock_repo).strip() if backport_rev: print(f'{cpython_rev} backported in {backport_rev}') return True print(f'{cpython_rev} has not been backported') def extract_patch_for(cpython_repo, rev): return git(f'format-patch -1 --no-stat --keep-subject --signoff --stdout {rev}', repo=cpython_repo) def munge(rev, patch): sign_off = 'Signed-off-by:' patch = patch.replace(sign_off, f'Backports: {rev}\n{sign_off}', 1) for pattern, sub in ( ('(a|b)/Lib/unittest/mock.py', r'\1/mock/mock.py'), (r'(a|b)/Lib/unittest/test/testmock/(\S+)', r'\1/mock/tests/\2'), ('(a|b)/Misc/NEWS', r'\1/NEWS'), ('(a|b)/NEWS.d/next/[^/]+/(.+\.rst)', r'\1/NEWS.d/\2'), ): patch = re.sub(pattern, sub, patch) return patch def apply_patch(mock_repo, rev, patch): patch_path = f'/tmp/{rev}.mock.patch' with open(patch_path, 'w') as target: target.write(patch) print(f'wrote {patch_path}') call(f'git am -k ' f'--include "mock/*" --include NEWS --include "NEWS.d/*" ' f'--reject {patch_path} ', cwd=mock_repo, shell=True) def update_last_sync(mock_repo, rev): with open(join(mock_repo, 'lastsync.txt'), 'w') as target: target.write(rev+'\n') print(f'update lastsync.txt to {rev}') def rev_from_mock_patch(text): match = re.search('Backports: ([a-z0-9]+)', text) return match.group(1) def skip_current(mock_repo, reason): text = git('am --show-current-patch', repo=mock_repo) rev = rev_from_mock_patch(text) git('am --abort', repo=mock_repo) print(f'skipping {rev}') update_last_sync(mock_repo, rev) call(f'git commit -m "Backports: {rev}, skipped: {reason}" lastsync.txt', shell=True, cwd=mock_repo) cleanup_old_patches(mock_repo) def commit_last_sync(revs, mock_repo): print('Yay! All caught up!') if len(revs): git('commit -m "latest sync point" lastsync.txt', repo=mock_repo) def main(): args = parse_args() if args.skip_current: return skip_current(args.mock, args.skip_reason) if repo_state_bad(args.mock): return cleanup_old_patches(args.mock) initial_cpython_rev = find_initial_cpython_rev() revs = cpython_revs_affecting_mock(args.cpython, initial_cpython_rev) for rev in revs: if has_been_backported(args.mock, rev): update_last_sync(args.mock, rev) continue patch = extract_patch_for(args.cpython, rev) patch = munge(rev, patch) apply_patch(args.mock, rev, patch) break else: commit_last_sync(revs, args.mock) def parse_args(): parser = ArgumentParser() parser.add_argument('--cpython', default='../cpython') parser.add_argument('--mock', default=abspath(dirname(__file__))) parser.add_argument('--skip-current', action='store_true') parser.add_argument('--skip-reason', default='it has no changes needed here.') return parser.parse_args() if __name__ == '__main__': main() mock-4.0.3/docs/000077500000000000000000000000001376434722300134125ustar00rootroot00000000000000mock-4.0.3/docs/changelog.txt000066400000000000000000000000631376434722300161010ustar00rootroot00000000000000Changelog ========= .. include:: ../CHANGELOG.rst mock-4.0.3/docs/conf.py000066400000000000000000000142571376434722300147220ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Mock documentation build configuration file, created by # sphinx-quickstart on Mon Nov 17 18:12:00 2008. # # This file is execfile()d with the current directory set to its containing dir. # # The contents of this file are pickled, so don't put values in the namespace # that aren't pickleable (module imports are okay, they're removed automatically). # # All configuration values have a default value; values that are commented out # serve to show the default value. import sys, os sys.path.insert(0, os.path.abspath('..')) import mock # If your extensions are in another directory, add it here. If the directory # is relative to the documentation root, use os.path.abspath to make it # absolute, like shown here. #sys.path.append(os.path.abspath('some/directory')) # General configuration # --------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.intersphinx', ] intersphinx_mapping = { 'python': ('http://docs.python.org/dev', None), } doctest_global_setup = """ import os import sys import mock from mock import * # yeah, I know :-/ import __main__ if os.getcwd() not in sys.path: sys.path.append(os.getcwd()) # keep a reference to __main__ sys.modules['__main'] = __main__ class ProxyModule(object): def __init__(self): self.__dict__ = globals() sys.modules['__main__'] = ProxyModule() """ doctest_global_cleanup = """ sys.modules['__main__'] = sys.modules['__main'] """ html_theme = 'nature' html_theme_options = {} # Add any paths that contain templates here, relative to this directory. #templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.txt' # The master toctree document. master_doc = 'index' # General substitutions. project = u'Mock' copyright = u'2007-2015, Michael Foord & the mock team' # The default replacements for |version| and |release|, also used in various # other places throughout the built documents. Supplied by pbr. # version = release = mock.__version__ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: (Set from pbr) today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. #unused_docs = [] # List of directories, relative to source directories, that shouldn't be searched # for source files. exclude_trees = [] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = False # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'friendly' # Options for HTML output # ----------------------- # The style sheet to use for HTML and HTML Help pages. A file of that name # must exist either in Sphinx' static/ path, or in one of the custom paths # given in html_static_path. #html_style = 'adctheme.css' # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". #html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. html_use_modindex = False # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, the reST sources are included in the HTML build as _sources/. #html_copy_source = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'Mockdoc' # Options for LaTeX output # ------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). latex_font_size = '12pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, document class [howto/manual]). latex_documents = [ ('index', 'Mock.tex', u'Mock Documentation', u'Michael Foord', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. latex_use_modindex = False mock-4.0.3/docs/index.txt000066400000000000000000000127601376434722300152700ustar00rootroot00000000000000=================================== Mock - Mocking and Testing Library =================================== .. include:: ../README.rst .. module:: mock :synopsis: Mock object and testing library. .. index:: introduction .. toctree:: :hidden: changelog Python Version Compatibility ++++++++++++++++++++++++++++ * Version 1.0.1 is the last version compatible with Python < 2.6. * Version 1.3.0 is the last version compatible with Python 3.2. * Version 2.0.0 is the last version compatible with Python 2.6. * Version 2.0.0 is the last version offering official Jython support. * version 3.0.5 is the last version supporting Python 3.5 and lower. .. index:: installing .. _installing: Installing ++++++++++ .. index:: repository .. index:: git You can checkout the latest development version from GitHub repository with the following command: ``git clone https://github.com/testing-cabal/mock.git`` .. index:: pip You can install mock with pip: | ``pip install -U mock`` .. index:: bug reports Bug Reports +++++++++++ Issues with the backport process, such as compatibility with a particular Python, should be reported to the `bug tracker `_. Feature requests and issues with Mock functionality should be reported to the `Python bug tracker `_. .. index:: python changes Changelog +++++++++ See the :doc:`change log `. .. index:: maintainer notes Maintainer Notes ++++++++++++++++ Development ----------- Checkout from git (see :ref:`installing`) and submit pull requests. Committers can just push as desired: since all semantic development takes place in cPython, the backport process is as lightweight as we can make it. If you end up fixing anything backport-specific, please add an entry to the top of ``CHANGELOG.rst`` so it shows up in the next release notes. Releasing --------- NB: please use semver. Bump the major component on API breaks, minor on all non-bugfix changes, patch on bugfix only changes. 1. Run ``release.py [major|minor|bugfix]`` which will roll out new NEWS items, bump the version number and create a commit for the release. 2. Review that commit, feel free to amend it if you want to note anything manually in ``CHANGELOG.rst``. 3. Push to the ``master`` branch on https://github.com/testing-cabal/mock.git and the Circle CI automation will take care of pushing releases to PyPI and creating a tag. Backporting rules ----------------- - If code such as this causes coverage checking to drop below 100%: .. code-block:: python def will_never_be_called(): pass It should be adjusted to the following pattern, preferably upstream, so that the ``.coveragerc`` in this repo knows to ignore it: .. code-block:: python def will_never_be_called(): pass - If code such as this causes coverage checking to drop below 100%: .. code-block:: python def will_never_be_called(): yield It should be adjusted to the following pattern, preferably upstream, so that the ``.coveragerc`` in this repo knows to ignore it: .. code-block:: python def will_never_be_called(): yield Backporting process ------------------- 1. Clone cpython and mock into the same directory, eg: .. code-block:: bash mkdir vcs cd vcs git clone https://github.com/python/cpython.git git clone https://github.com/testing-cabal/mock.git Make sure they are both on master and up to date! 2. Create a branch in your ``mock`` clone and switch to it. 3. Make sure you build a suitable virtualenv for Mock development and activate it. For backporting, this should use Python 3.7+. 4. Run ``backport.py``: .. code-block:: bash cd vcs/mock python backport.py This will find the next cpython patch that needs to be applied, munge it and attempt to apply it with ``git am``. If it succeeds, run the tests and/or push your branch up to a fork and do a pull request into the master branch of the main repo to kick off the continuous integration tests. If it fails, you'll have to manually work with what ``git status`` shows to get the patch committed. If it turns out that there's nothing that should be applied from the failed commit, run ``python backport.py --skip-current``, maybe with ``--skip-reason``. If you have to make changes, please do a ``git commit --amend`` and add notes about what needed doing below the ``Signed-off-by`` block. If you have to make changes because tests fail with an applied patch, please make those changes in a followup commit and take note of the "Backporting rules" above. 5. Rinse and repeat until ``backport.py`` reports no more patches need applying. 6. If ``backport.py`` has updated ``lastsync.txt`` but not committed it, now would be a good time to commit that change. Checking coverage in upstream ----------------------------- Assuming you have the checkout structure as above, and you have compiled your cpython master branch, then roughly as follows: .. code-block:: bash ~/vcs/cpython/python.exe -m venv ~/virtualenvs/cpython-master source ~/virtualenvs/cpython-master/bin/activate pip install -U setuptools pip pip install pytest pytest-cov cd vcs/cpython/Lib/unittest pytest --cov unittest.mock --cov unittest.test.testmock \ --cov-config ~/vcs/git/mock/.coveragerc \ --cov-report term-missing:skip-covered \ test/testmock/test* Ignore ``test/testmock/__*__.py`` as these aren't present in the backport. mock-4.0.3/lastsync.txt000066400000000000000000000000511376434722300150570ustar00rootroot00000000000000c598a04dd29b89ad072245ddaf738badcfb41ac7 mock-4.0.3/mock/000077500000000000000000000000001376434722300134135ustar00rootroot00000000000000mock-4.0.3/mock/__init__.py000066400000000000000000000005161376434722300155260ustar00rootroot00000000000000from __future__ import absolute_import import re, sys IS_PYPY = 'PyPy' in sys.version import mock.mock as _mock from mock.mock import * __version__ = '4.0.3' version_info = tuple(int(p) for p in re.match(r'(\d+).(\d+).(\d+)', __version__).groups()) __all__ = ('__version__', 'version_info') + _mock.__all__ mock-4.0.3/mock/backports.py000066400000000000000000000053701376434722300157620ustar00rootroot00000000000000import sys if sys.version_info[:2] < (3, 8): import asyncio, functools from asyncio.coroutines import _is_coroutine from inspect import ismethod, isfunction, CO_COROUTINE from unittest import TestCase def _unwrap_partial(func): while isinstance(func, functools.partial): func = func.func return func def _has_code_flag(f, flag): """Return true if ``f`` is a function (or a method or functools.partial wrapper wrapping a function) whose code object has the given ``flag`` set in its flags.""" while ismethod(f): f = f.__func__ f = _unwrap_partial(f) if not isfunction(f): return False return bool(f.__code__.co_flags & flag) def iscoroutinefunction(obj): """Return true if the object is a coroutine function. Coroutine functions are defined with "async def" syntax. """ return ( _has_code_flag(obj, CO_COROUTINE) or getattr(obj, '_is_coroutine', None) is _is_coroutine ) class IsolatedAsyncioTestCase(TestCase): def __init__(self, methodName='runTest'): super().__init__(methodName) self._asyncioTestLoop = None self._asyncioCallsQueue = None async def _asyncioLoopRunner(self, fut): self._asyncioCallsQueue = queue = asyncio.Queue() fut.set_result(None) while True: query = await queue.get() queue.task_done() assert query is None def _setupAsyncioLoop(self): assert self._asyncioTestLoop is None loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.set_debug(True) self._asyncioTestLoop = loop fut = loop.create_future() self._asyncioCallsTask = loop.create_task(self._asyncioLoopRunner(fut)) loop.run_until_complete(fut) def _tearDownAsyncioLoop(self): assert self._asyncioTestLoop is not None loop = self._asyncioTestLoop self._asyncioTestLoop = None self._asyncioCallsQueue.put_nowait(None) loop.run_until_complete(self._asyncioCallsQueue.join()) try: # shutdown asyncgens loop.run_until_complete(loop.shutdown_asyncgens()) finally: asyncio.set_event_loop(None) loop.close() def run(self, result=None): self._setupAsyncioLoop() try: return super().run(result) finally: self._tearDownAsyncioLoop() else: from asyncio import iscoroutinefunction from unittest import IsolatedAsyncioTestCase mock-4.0.3/mock/mock.py000066400000000000000000003030061376434722300147200ustar00rootroot00000000000000# mock.py # Test tools for mocking and patching. # Maintained by Michael Foord # Backport for other versions of Python available from # https://pypi.org/project/mock __all__ = ( 'Mock', 'MagicMock', 'patch', 'sentinel', 'DEFAULT', 'ANY', 'call', 'create_autospec', 'AsyncMock', 'FILTER_DIR', 'NonCallableMock', 'NonCallableMagicMock', 'mock_open', 'PropertyMock', 'seal', ) import asyncio import contextlib import io import inspect import pprint import sys import builtins from asyncio import iscoroutinefunction from types import CodeType, ModuleType, MethodType from unittest.util import safe_repr from functools import wraps, partial from mock import IS_PYPY from .backports import iscoroutinefunction _builtins = {name for name in dir(builtins) if not name.startswith('_')} FILTER_DIR = True # Workaround for issue #12370 # Without this, the __class__ properties wouldn't be set correctly _safe_super = super def _is_async_obj(obj): if _is_instance_mock(obj) and not isinstance(obj, AsyncMock): return False if hasattr(obj, '__func__'): obj = getattr(obj, '__func__') return iscoroutinefunction(obj) or inspect.isawaitable(obj) def _is_async_func(func): if getattr(func, '__code__', None): return iscoroutinefunction(func) else: return False def _is_instance_mock(obj): # can't use isinstance on Mock objects because they override __class__ # The base class for all mocks is NonCallableMock return issubclass(type(obj), NonCallableMock) def _is_exception(obj): return ( isinstance(obj, BaseException) or isinstance(obj, type) and issubclass(obj, BaseException) ) def _extract_mock(obj): # Autospecced functions will return a FunctionType with "mock" attribute # which is the actual mock object that needs to be used. if isinstance(obj, FunctionTypes) and hasattr(obj, 'mock'): return obj.mock else: return obj def _get_signature_object(func, as_instance, eat_self): """ Given an arbitrary, possibly callable object, try to create a suitable signature object. Return a (reduced func, signature) tuple, or None. """ if isinstance(func, type) and not as_instance: # If it's a type and should be modelled as a type, use __init__. func = func.__init__ # Skip the `self` argument in __init__ eat_self = True elif not isinstance(func, FunctionTypes): # If we really want to model an instance of the passed type, # __call__ should be looked up, not __init__. try: func = func.__call__ except AttributeError: return None if eat_self: sig_func = partial(func, None) else: sig_func = func try: return func, inspect.signature(sig_func) except ValueError: # Certain callable types are not supported by inspect.signature() return None def _check_signature(func, mock, skipfirst, instance=False): sig = _get_signature_object(func, instance, skipfirst) if sig is None: return func, sig = sig def checksig(_mock_self, *args, **kwargs): sig.bind(*args, **kwargs) _copy_func_details(func, checksig) type(mock)._mock_check_sig = checksig type(mock).__signature__ = sig def _copy_func_details(func, funcopy): # we explicitly don't copy func.__dict__ into this copy as it would # expose original attributes that should be mocked for attribute in ( '__name__', '__doc__', '__text_signature__', '__module__', '__defaults__', '__kwdefaults__', ): try: setattr(funcopy, attribute, getattr(func, attribute)) except AttributeError: pass def _callable(obj): if isinstance(obj, type): return True if isinstance(obj, (staticmethod, classmethod, MethodType)): return _callable(obj.__func__) if getattr(obj, '__call__', None) is not None: return True return False def _is_list(obj): # checks for list or tuples # XXXX badly named! return type(obj) in (list, tuple) def _instance_callable(obj): """Given an object, return True if the object is callable. For classes, return True if instances would be callable.""" if not isinstance(obj, type): # already an instance return getattr(obj, '__call__', None) is not None # *could* be broken by a class overriding __mro__ or __dict__ via # a metaclass for base in (obj,) + obj.__mro__: if base.__dict__.get('__call__') is not None: return True return False def _set_signature(mock, original, instance=False): # creates a function with signature (*args, **kwargs) that delegates to a # mock. It still does signature checking by calling a lambda with the same # signature as the original. skipfirst = isinstance(original, type) result = _get_signature_object(original, instance, skipfirst) if result is None: return mock func, sig = result def checksig(*args, **kwargs): sig.bind(*args, **kwargs) _copy_func_details(func, checksig) name = original.__name__ if not name.isidentifier(): name = 'funcopy' context = {'_checksig_': checksig, 'mock': mock} src = """def %s(*args, **kwargs): _checksig_(*args, **kwargs) return mock(*args, **kwargs)""" % name exec (src, context) funcopy = context[name] _setup_func(funcopy, mock, sig) return funcopy def _setup_func(funcopy, mock, sig): funcopy.mock = mock def assert_called_with(*args, **kwargs): return mock.assert_called_with(*args, **kwargs) def assert_called(*args, **kwargs): return mock.assert_called(*args, **kwargs) def assert_not_called(*args, **kwargs): return mock.assert_not_called(*args, **kwargs) def assert_called_once(*args, **kwargs): return mock.assert_called_once(*args, **kwargs) def assert_called_once_with(*args, **kwargs): return mock.assert_called_once_with(*args, **kwargs) def assert_has_calls(*args, **kwargs): return mock.assert_has_calls(*args, **kwargs) def assert_any_call(*args, **kwargs): return mock.assert_any_call(*args, **kwargs) def reset_mock(): funcopy.method_calls = _CallList() funcopy.mock_calls = _CallList() mock.reset_mock() ret = funcopy.return_value if _is_instance_mock(ret) and not ret is mock: ret.reset_mock() funcopy.called = False funcopy.call_count = 0 funcopy.call_args = None funcopy.call_args_list = _CallList() funcopy.method_calls = _CallList() funcopy.mock_calls = _CallList() funcopy.return_value = mock.return_value funcopy.side_effect = mock.side_effect funcopy._mock_children = mock._mock_children funcopy.assert_called_with = assert_called_with funcopy.assert_called_once_with = assert_called_once_with funcopy.assert_has_calls = assert_has_calls funcopy.assert_any_call = assert_any_call funcopy.reset_mock = reset_mock funcopy.assert_called = assert_called funcopy.assert_not_called = assert_not_called funcopy.assert_called_once = assert_called_once funcopy.__signature__ = sig mock._mock_delegate = funcopy def _setup_async_mock(mock): mock._is_coroutine = asyncio.coroutines._is_coroutine mock.await_count = 0 mock.await_args = None mock.await_args_list = _CallList() # Mock is not configured yet so the attributes are set # to a function and then the corresponding mock helper function # is called when the helper is accessed similar to _setup_func. def wrapper(attr, *args, **kwargs): return getattr(mock.mock, attr)(*args, **kwargs) for attribute in ('assert_awaited', 'assert_awaited_once', 'assert_awaited_with', 'assert_awaited_once_with', 'assert_any_await', 'assert_has_awaits', 'assert_not_awaited'): # setattr(mock, attribute, wrapper) causes late binding # hence attribute will always be the last value in the loop # Use partial(wrapper, attribute) to ensure the attribute is bound # correctly. setattr(mock, attribute, partial(wrapper, attribute)) def _is_magic(name): return '__%s__' % name[2:-2] == name class _SentinelObject(object): "A unique, named, sentinel object." def __init__(self, name): self.name = name def __repr__(self): return 'sentinel.%s' % self.name def __reduce__(self): return 'sentinel.%s' % self.name class _Sentinel(object): """Access attributes to return a named object, usable as a sentinel.""" def __init__(self): self._sentinels = {} def __getattr__(self, name): if name == '__bases__': # Without this help(unittest.mock) raises an exception raise AttributeError return self._sentinels.setdefault(name, _SentinelObject(name)) def __reduce__(self): return 'sentinel' sentinel = _Sentinel() DEFAULT = sentinel.DEFAULT _missing = sentinel.MISSING _deleted = sentinel.DELETED _allowed_names = { 'return_value', '_mock_return_value', 'side_effect', '_mock_side_effect', '_mock_parent', '_mock_new_parent', '_mock_name', '_mock_new_name' } def _delegating_property(name): _allowed_names.add(name) _the_name = '_mock_' + name def _get(self, name=name, _the_name=_the_name): sig = self._mock_delegate if sig is None: return getattr(self, _the_name) return getattr(sig, name) def _set(self, value, name=name, _the_name=_the_name): sig = self._mock_delegate if sig is None: self.__dict__[_the_name] = value else: setattr(sig, name, value) return property(_get, _set) class _CallList(list): def __contains__(self, value): if not isinstance(value, list): return list.__contains__(self, value) len_value = len(value) len_self = len(self) if len_value > len_self: return False for i in range(0, len_self - len_value + 1): sub_list = self[i:i+len_value] if sub_list == value: return True return False def __repr__(self): return pprint.pformat(list(self)) def _check_and_set_parent(parent, value, name, new_name): value = _extract_mock(value) if not _is_instance_mock(value): return False if ((value._mock_name or value._mock_new_name) or (value._mock_parent is not None) or (value._mock_new_parent is not None)): return False _parent = parent while _parent is not None: # setting a mock (value) as a child or return value of itself # should not modify the mock if _parent is value: return False _parent = _parent._mock_new_parent if new_name: value._mock_new_parent = parent value._mock_new_name = new_name if name: value._mock_parent = parent value._mock_name = name return True # Internal class to identify if we wrapped an iterator object or not. class _MockIter(object): def __init__(self, obj): self.obj = iter(obj) def __next__(self): return next(self.obj) class Base(object): _mock_return_value = DEFAULT _mock_side_effect = None def __init__(self, *args, **kwargs): pass class NonCallableMock(Base): """A non-callable version of `Mock`""" def __new__(cls, *args, **kw): # every instance has its own class # so we can create magic methods on the # class without stomping on other mocks bases = (cls,) if not issubclass(cls, AsyncMockMixin): # Check if spec is an async object or function bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments spec_arg = bound_args.get('spec_set', bound_args.get('spec')) if spec_arg is not None and _is_async_obj(spec_arg): bases = (AsyncMockMixin, cls) new = type(cls.__name__, bases, {'__doc__': cls.__doc__}) instance = _safe_super(NonCallableMock, cls).__new__(new) return instance def __init__( self, spec=None, wraps=None, name=None, spec_set=None, parent=None, _spec_state=None, _new_name='', _new_parent=None, _spec_as_instance=False, _eat_self=None, unsafe=False, **kwargs ): if _new_parent is None: _new_parent = parent __dict__ = self.__dict__ __dict__['_mock_parent'] = parent __dict__['_mock_name'] = name __dict__['_mock_new_name'] = _new_name __dict__['_mock_new_parent'] = _new_parent __dict__['_mock_sealed'] = False if spec_set is not None: spec = spec_set spec_set = True if _eat_self is None: _eat_self = parent is not None self._mock_add_spec(spec, spec_set, _spec_as_instance, _eat_self) __dict__['_mock_children'] = {} __dict__['_mock_wraps'] = wraps __dict__['_mock_delegate'] = None __dict__['_mock_called'] = False __dict__['_mock_call_args'] = None __dict__['_mock_call_count'] = 0 __dict__['_mock_call_args_list'] = _CallList() __dict__['_mock_mock_calls'] = _CallList() __dict__['method_calls'] = _CallList() __dict__['_mock_unsafe'] = unsafe if kwargs: self.configure_mock(**kwargs) _safe_super(NonCallableMock, self).__init__( spec, wraps, name, spec_set, parent, _spec_state ) def attach_mock(self, mock, attribute): """ Attach a mock as an attribute of this one, replacing its name and parent. Calls to the attached mock will be recorded in the `method_calls` and `mock_calls` attributes of this one.""" inner_mock = _extract_mock(mock) inner_mock._mock_parent = None inner_mock._mock_new_parent = None inner_mock._mock_name = '' inner_mock._mock_new_name = None setattr(self, attribute, mock) def mock_add_spec(self, spec, spec_set=False): """Add a spec to a mock. `spec` can either be an object or a list of strings. Only attributes on the `spec` can be fetched as attributes from the mock. If `spec_set` is True then only attributes on the spec can be set.""" self._mock_add_spec(spec, spec_set) def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, _eat_self=False): _spec_class = None _spec_signature = None _spec_asyncs = [] for attr in dir(spec): if iscoroutinefunction(getattr(spec, attr, None)): _spec_asyncs.append(attr) if spec is not None and not _is_list(spec): if isinstance(spec, type): _spec_class = spec else: _spec_class = type(spec) res = _get_signature_object(spec, _spec_as_instance, _eat_self) _spec_signature = res and res[1] spec = dir(spec) __dict__ = self.__dict__ __dict__['_spec_class'] = _spec_class __dict__['_spec_set'] = spec_set __dict__['_spec_signature'] = _spec_signature __dict__['_mock_methods'] = spec __dict__['_spec_asyncs'] = _spec_asyncs def __get_return_value(self): ret = self._mock_return_value if self._mock_delegate is not None: ret = self._mock_delegate.return_value if ret is DEFAULT: ret = self._get_child_mock( _new_parent=self, _new_name='()' ) self.return_value = ret return ret def __set_return_value(self, value): if self._mock_delegate is not None: self._mock_delegate.return_value = value else: self._mock_return_value = value _check_and_set_parent(self, value, None, '()') __return_value_doc = "The value to be returned when the mock is called." return_value = property(__get_return_value, __set_return_value, __return_value_doc) @property def __class__(self): if self._spec_class is None: return type(self) return self._spec_class called = _delegating_property('called') call_count = _delegating_property('call_count') call_args = _delegating_property('call_args') call_args_list = _delegating_property('call_args_list') mock_calls = _delegating_property('mock_calls') def __get_side_effect(self): delegated = self._mock_delegate if delegated is None: return self._mock_side_effect sf = delegated.side_effect if (sf is not None and not callable(sf) and not isinstance(sf, _MockIter) and not _is_exception(sf)): sf = _MockIter(sf) delegated.side_effect = sf return sf def __set_side_effect(self, value): value = _try_iter(value) delegated = self._mock_delegate if delegated is None: self._mock_side_effect = value else: delegated.side_effect = value side_effect = property(__get_side_effect, __set_side_effect) def reset_mock(self, visited=None,*, return_value=False, side_effect=False): "Restore the mock object to its initial state." if visited is None: visited = [] if id(self) in visited: return visited.append(id(self)) self.called = False self.call_args = None self.call_count = 0 self.mock_calls = _CallList() self.call_args_list = _CallList() self.method_calls = _CallList() if return_value: self._mock_return_value = DEFAULT if side_effect: self._mock_side_effect = None for child in self._mock_children.values(): if isinstance(child, _SpecState) or child is _deleted: continue child.reset_mock(visited, return_value=return_value, side_effect=side_effect) ret = self._mock_return_value if _is_instance_mock(ret) and ret is not self: ret.reset_mock(visited) def configure_mock(self, **kwargs): """Set attributes on the mock through keyword arguments. Attributes plus return values and side effects can be set on child mocks using standard dot notation and unpacking a dictionary in the method call: >>> attrs = {'method.return_value': 3, 'other.side_effect': KeyError} >>> mock.configure_mock(**attrs)""" for arg, val in sorted(kwargs.items(), # we sort on the number of dots so that # attributes are set before we set attributes on # attributes key=lambda entry: entry[0].count('.')): args = arg.split('.') final = args.pop() obj = self for entry in args: obj = getattr(obj, entry) setattr(obj, final, val) def __getattr__(self, name): if name in {'_mock_methods', '_mock_unsafe'}: raise AttributeError(name) elif self._mock_methods is not None: if name not in self._mock_methods or name in _all_magics: raise AttributeError("Mock object has no attribute %r" % name) elif _is_magic(name): raise AttributeError(name) if not self._mock_unsafe: if name.startswith(('assert', 'assret', 'asert', 'aseert', 'assrt')): raise AttributeError("Attributes cannot start with 'assert' " "or its misspellings") result = self._mock_children.get(name) if result is _deleted: raise AttributeError(name) elif result is None: wraps = None if self._mock_wraps is not None: # XXXX should we get the attribute without triggering code # execution? wraps = getattr(self._mock_wraps, name) result = self._get_child_mock( parent=self, name=name, wraps=wraps, _new_name=name, _new_parent=self ) self._mock_children[name] = result elif isinstance(result, _SpecState): result = create_autospec( result.spec, result.spec_set, result.instance, result.parent, result.name ) self._mock_children[name] = result return result def _extract_mock_name(self): _name_list = [self._mock_new_name] _parent = self._mock_new_parent last = self dot = '.' if _name_list == ['()']: dot = '' while _parent is not None: last = _parent _name_list.append(_parent._mock_new_name + dot) dot = '.' if _parent._mock_new_name == '()': dot = '' _parent = _parent._mock_new_parent _name_list = list(reversed(_name_list)) _first = last._mock_name or 'mock' if len(_name_list) > 1: if _name_list[1] not in ('()', '().'): _first += '.' _name_list[0] = _first return ''.join(_name_list) def __repr__(self): name = self._extract_mock_name() name_string = '' if name not in ('mock', 'mock.'): name_string = ' name=%r' % name spec_string = '' if self._spec_class is not None: spec_string = ' spec=%r' if self._spec_set: spec_string = ' spec_set=%r' spec_string = spec_string % self._spec_class.__name__ return "<%s%s%s id='%s'>" % ( type(self).__name__, name_string, spec_string, id(self) ) def __dir__(self): """Filter the output of `dir(mock)` to only useful members.""" if not FILTER_DIR: return object.__dir__(self) extras = self._mock_methods or [] from_type = dir(type(self)) from_dict = list(self.__dict__) from_child_mocks = [ m_name for m_name, m_value in self._mock_children.items() if m_value is not _deleted] from_type = [e for e in from_type if not e.startswith('_')] from_dict = [e for e in from_dict if not e.startswith('_') or _is_magic(e)] return sorted(set(extras + from_type + from_dict + from_child_mocks)) def __setattr__(self, name, value): if name in _allowed_names: # property setters go through here return object.__setattr__(self, name, value) elif (self._spec_set and self._mock_methods is not None and name not in self._mock_methods and name not in self.__dict__): raise AttributeError("Mock object has no attribute '%s'" % name) elif name in _unsupported_magics: msg = 'Attempting to set unsupported magic method %r.' % name raise AttributeError(msg) elif name in _all_magics: if self._mock_methods is not None and name not in self._mock_methods: raise AttributeError("Mock object has no attribute '%s'" % name) if not _is_instance_mock(value): setattr(type(self), name, _get_method(name, value)) original = value value = lambda *args, **kw: original(self, *args, **kw) else: # only set _new_name and not name so that mock_calls is tracked # but not method calls _check_and_set_parent(self, value, None, name) setattr(type(self), name, value) self._mock_children[name] = value elif name == '__class__': self._spec_class = value return else: if _check_and_set_parent(self, value, name, name): self._mock_children[name] = value if self._mock_sealed and not hasattr(self, name): mock_name = f'{self._extract_mock_name()}.{name}' raise AttributeError(f'Cannot set {mock_name}') return object.__setattr__(self, name, value) def __delattr__(self, name): if name in _all_magics and name in type(self).__dict__: delattr(type(self), name) if name not in self.__dict__: # for magic methods that are still MagicProxy objects and # not set on the instance itself return obj = self._mock_children.get(name, _missing) if name in self.__dict__: _safe_super(NonCallableMock, self).__delattr__(name) elif obj is _deleted: raise AttributeError(name) if obj is not _missing: del self._mock_children[name] self._mock_children[name] = _deleted def _format_mock_call_signature(self, args, kwargs): name = self._mock_name or 'mock' return _format_call_signature(name, args, kwargs) def _format_mock_failure_message(self, args, kwargs, action='call'): message = 'expected %s not found.\nExpected: %s\nActual: %s' expected_string = self._format_mock_call_signature(args, kwargs) call_args = self.call_args actual_string = self._format_mock_call_signature(*call_args) return message % (action, expected_string, actual_string) def _get_call_signature_from_name(self, name): """ * If call objects are asserted against a method/function like obj.meth1 then there could be no name for the call object to lookup. Hence just return the spec_signature of the method/function being asserted against. * If the name is not empty then remove () and split by '.' to get list of names to iterate through the children until a potential match is found. A child mock is created only during attribute access so if we get a _SpecState then no attributes of the spec were accessed and can be safely exited. """ if not name: return self._spec_signature sig = None names = name.replace('()', '').split('.') children = self._mock_children for name in names: child = children.get(name) if child is None or isinstance(child, _SpecState): break else: # If an autospecced object is attached using attach_mock the # child would be a function with mock object as attribute from # which signature has to be derived. child = _extract_mock(child) children = child._mock_children sig = child._spec_signature return sig def _call_matcher(self, _call): """ Given a call (or simply an (args, kwargs) tuple), return a comparison key suitable for matching with other calls. This is a best effort method which relies on the spec's signature, if available, or falls back on the arguments themselves. """ if isinstance(_call, tuple) and len(_call) > 2: sig = self._get_call_signature_from_name(_call[0]) else: sig = self._spec_signature if sig is not None: if len(_call) == 2: name = '' args, kwargs = _call else: name, args, kwargs = _call try: bound_call = sig.bind(*args, **kwargs) return call(name, bound_call.args, bound_call.kwargs) except TypeError as e: return e.with_traceback(None) else: return _call def assert_not_called(_mock_self): """assert that the mock was never called. """ self = _mock_self if self.call_count != 0: msg = ("Expected '%s' to not have been called. Called %s times.%s" % (self._mock_name or 'mock', self.call_count, self._calls_repr())) raise AssertionError(msg) def assert_called(_mock_self): """assert that the mock was called at least once """ self = _mock_self if self.call_count == 0: msg = ("Expected '%s' to have been called." % (self._mock_name or 'mock')) raise AssertionError(msg) def assert_called_once(_mock_self): """assert that the mock was called only once. """ self = _mock_self if not self.call_count == 1: msg = ("Expected '%s' to have been called once. Called %s times.%s" % (self._mock_name or 'mock', self.call_count, self._calls_repr())) raise AssertionError(msg) def assert_called_with(_mock_self, *args, **kwargs): """assert that the last call was made with the specified arguments. Raises an AssertionError if the args and keyword args passed in are different to the last call to the mock.""" self = _mock_self if self.call_args is None: expected = self._format_mock_call_signature(args, kwargs) actual = 'not called.' error_message = ('expected call not found.\nExpected: %s\nActual: %s' % (expected, actual)) raise AssertionError(error_message) def _error_message(): msg = self._format_mock_failure_message(args, kwargs) return msg expected = self._call_matcher(_Call((args, kwargs), two=True)) actual = self._call_matcher(self.call_args) if actual != expected: cause = expected if isinstance(expected, Exception) else None raise AssertionError(_error_message()) from cause def assert_called_once_with(_mock_self, *args, **kwargs): """assert that the mock was called exactly once and that that call was with the specified arguments.""" self = _mock_self if not self.call_count == 1: msg = ("Expected '%s' to be called once. Called %s times.%s" % (self._mock_name or 'mock', self.call_count, self._calls_repr())) raise AssertionError(msg) return self.assert_called_with(*args, **kwargs) def assert_has_calls(self, calls, any_order=False): """assert the mock has been called with the specified calls. The `mock_calls` list is checked for the calls. If `any_order` is False (the default) then the calls must be sequential. There can be extra calls before or after the specified calls. If `any_order` is True then the calls can be in any order, but they must all appear in `mock_calls`.""" expected = [self._call_matcher(c) for c in calls] cause = next((e for e in expected if isinstance(e, Exception)), None) all_calls = _CallList(self._call_matcher(c) for c in self.mock_calls) if not any_order: if expected not in all_calls: if cause is None: problem = 'Calls not found.' else: problem = ('Error processing expected calls.\n' 'Errors: {}').format( [e if isinstance(e, Exception) else None for e in expected]) raise AssertionError( f'{problem}\n' f'Expected: {_CallList(calls)}' f'{self._calls_repr(prefix="Actual").rstrip(".")}' ) from cause return all_calls = list(all_calls) not_found = [] for kall in expected: try: all_calls.remove(kall) except ValueError: not_found.append(kall) if not_found: raise AssertionError( '%r does not contain all of %r in its call list, ' 'found %r instead' % (self._mock_name or 'mock', tuple(not_found), all_calls) ) from cause def assert_any_call(self, *args, **kwargs): """assert the mock has been called with the specified arguments. The assert passes if the mock has *ever* been called, unlike `assert_called_with` and `assert_called_once_with` that only pass if the call is the most recent one.""" expected = self._call_matcher(_Call((args, kwargs), two=True)) cause = expected if isinstance(expected, Exception) else None actual = [self._call_matcher(c) for c in self.call_args_list] if cause or expected not in _AnyComparer(actual): expected_string = self._format_mock_call_signature(args, kwargs) raise AssertionError( '%s call not found' % expected_string ) from cause def _get_child_mock(self, **kw): """Create the child mocks for attributes and return value. By default child mocks will be the same type as the parent. Subclasses of Mock may want to override this to customize the way child mocks are made. For non-callable mocks the callable variant will be used (rather than any custom subclass).""" _new_name = kw.get("_new_name") if _new_name in self.__dict__['_spec_asyncs']: return AsyncMock(**kw) _type = type(self) if issubclass(_type, MagicMock) and _new_name in _async_method_magics: # Any asynchronous magic becomes an AsyncMock klass = AsyncMock elif issubclass(_type, AsyncMockMixin): if (_new_name in _all_sync_magics or self._mock_methods and _new_name in self._mock_methods): # Any synchronous method on AsyncMock becomes a MagicMock klass = MagicMock else: klass = AsyncMock elif not issubclass(_type, CallableMixin): if issubclass(_type, NonCallableMagicMock): klass = MagicMock elif issubclass(_type, NonCallableMock): klass = Mock else: klass = _type.__mro__[1] if self._mock_sealed: attribute = "." + kw["name"] if "name" in kw else "()" mock_name = self._extract_mock_name() + attribute raise AttributeError(mock_name) return klass(**kw) def _calls_repr(self, prefix="Calls"): """Renders self.mock_calls as a string. Example: "\nCalls: [call(1), call(2)]." If self.mock_calls is empty, an empty string is returned. The output will be truncated if very long. """ if not self.mock_calls: return "" return f"\n{prefix}: {safe_repr(self.mock_calls)}." _MOCK_SIG = inspect.signature(NonCallableMock.__init__) class _AnyComparer(list): """A list which checks if it contains a call which may have an argument of ANY, flipping the components of item and self from their traditional locations so that ANY is guaranteed to be on the left.""" def __contains__(self, item): for _call in self: assert len(item) == len(_call) if all([ expected == actual for expected, actual in zip(item, _call) ]): return True return False def _try_iter(obj): if obj is None: return obj if _is_exception(obj): return obj if _callable(obj): return obj try: return iter(obj) except TypeError: # XXXX backwards compatibility # but this will blow up on first call - so maybe we should fail early? return obj class CallableMixin(Base): def __init__(self, spec=None, side_effect=None, return_value=DEFAULT, wraps=None, name=None, spec_set=None, parent=None, _spec_state=None, _new_name='', _new_parent=None, **kwargs): self.__dict__['_mock_return_value'] = return_value _safe_super(CallableMixin, self).__init__( spec, wraps, name, spec_set, parent, _spec_state, _new_name, _new_parent, **kwargs ) self.side_effect = side_effect def _mock_check_sig(self, *args, **kwargs): # stub method that can be replaced with one with a specific signature pass def __call__(_mock_self, *args, **kwargs): # can't use self in-case a function / method we are mocking uses self # in the signature _mock_self._mock_check_sig(*args, **kwargs) _mock_self._increment_mock_call(*args, **kwargs) return _mock_self._mock_call(*args, **kwargs) def _mock_call(_mock_self, *args, **kwargs): return _mock_self._execute_mock_call(*args, **kwargs) def _increment_mock_call(_mock_self, *args, **kwargs): self = _mock_self self.called = True self.call_count += 1 # handle call_args # needs to be set here so assertions on call arguments pass before # execution in the case of awaited calls _call = _Call((args, kwargs), two=True) self.call_args = _call self.call_args_list.append(_call) # initial stuff for method_calls: do_method_calls = self._mock_parent is not None method_call_name = self._mock_name # initial stuff for mock_calls: mock_call_name = self._mock_new_name is_a_call = mock_call_name == '()' self.mock_calls.append(_Call(('', args, kwargs))) # follow up the chain of mocks: _new_parent = self._mock_new_parent while _new_parent is not None: # handle method_calls: if do_method_calls: _new_parent.method_calls.append(_Call((method_call_name, args, kwargs))) do_method_calls = _new_parent._mock_parent is not None if do_method_calls: method_call_name = _new_parent._mock_name + '.' + method_call_name # handle mock_calls: this_mock_call = _Call((mock_call_name, args, kwargs)) _new_parent.mock_calls.append(this_mock_call) if _new_parent._mock_new_name: if is_a_call: dot = '' else: dot = '.' is_a_call = _new_parent._mock_new_name == '()' mock_call_name = _new_parent._mock_new_name + dot + mock_call_name # follow the parental chain: _new_parent = _new_parent._mock_new_parent def _execute_mock_call(_mock_self, *args, **kwargs): self = _mock_self # separate from _increment_mock_call so that awaited functions are # executed separately from their call, also AsyncMock overrides this method effect = self.side_effect if effect is not None: if _is_exception(effect): raise effect elif not _callable(effect): result = next(effect) if _is_exception(result): raise result else: result = effect(*args, **kwargs) if result is not DEFAULT: return result if self._mock_return_value is not DEFAULT: return self.return_value if self._mock_wraps is not None: return self._mock_wraps(*args, **kwargs) return self.return_value class Mock(CallableMixin, NonCallableMock): """ Create a new `Mock` object. `Mock` takes several optional arguments that specify the behaviour of the Mock object: * `spec`: This can be either a list of strings or an existing object (a class or instance) that acts as the specification for the mock object. If you pass in an object then a list of strings is formed by calling dir on the object (excluding unsupported magic attributes and methods). Accessing any attribute not in this list will raise an `AttributeError`. If `spec` is an object (rather than a list of strings) then `mock.__class__` returns the class of the spec object. This allows mocks to pass `isinstance` tests. * `spec_set`: A stricter variant of `spec`. If used, attempting to *set* or get an attribute on the mock that isn't on the object passed as `spec_set` will raise an `AttributeError`. * `side_effect`: A function to be called whenever the Mock is called. See the `side_effect` attribute. Useful for raising exceptions or dynamically changing return values. The function is called with the same arguments as the mock, and unless it returns `DEFAULT`, the return value of this function is used as the return value. If `side_effect` is an iterable then each call to the mock will return the next value from the iterable. If any of the members of the iterable are exceptions they will be raised instead of returned. * `return_value`: The value returned when the mock is called. By default this is a new Mock (created on first access). See the `return_value` attribute. * `wraps`: Item for the mock object to wrap. If `wraps` is not None then calling the Mock will pass the call through to the wrapped object (returning the real result). Attribute access on the mock will return a Mock object that wraps the corresponding attribute of the wrapped object (so attempting to access an attribute that doesn't exist will raise an `AttributeError`). If the mock has an explicit `return_value` set then calls are not passed to the wrapped object and the `return_value` is returned instead. * `name`: If the mock has a name then it will be used in the repr of the mock. This can be useful for debugging. The name is propagated to child mocks. Mocks can also be called with arbitrary keyword arguments. These will be used to set attributes on the mock after it is created. """ def _dot_lookup(thing, comp, import_path): try: return getattr(thing, comp) except AttributeError: __import__(import_path) return getattr(thing, comp) def _importer(target): components = target.split('.') import_path = components.pop(0) thing = __import__(import_path) for comp in components: import_path += ".%s" % comp thing = _dot_lookup(thing, comp, import_path) return thing class _patch(object): attribute_name = None _active_patches = [] def __init__( self, getter, attribute, new, spec, create, spec_set, autospec, new_callable, kwargs ): if new_callable is not None: if new is not DEFAULT: raise ValueError( "Cannot use 'new' and 'new_callable' together" ) if autospec is not None: raise ValueError( "Cannot use 'autospec' and 'new_callable' together" ) self.getter = getter self.attribute = attribute self.new = new self.new_callable = new_callable self.spec = spec self.create = create self.has_local = False self.spec_set = spec_set self.autospec = autospec self.kwargs = kwargs self.additional_patchers = [] def copy(self): patcher = _patch( self.getter, self.attribute, self.new, self.spec, self.create, self.spec_set, self.autospec, self.new_callable, self.kwargs ) patcher.attribute_name = self.attribute_name patcher.additional_patchers = [ p.copy() for p in self.additional_patchers ] return patcher def __call__(self, func): if isinstance(func, type): return self.decorate_class(func) if inspect.iscoroutinefunction(func): return self.decorate_async_callable(func) return self.decorate_callable(func) def decorate_class(self, klass): for attr in dir(klass): if not attr.startswith(patch.TEST_PREFIX): continue attr_value = getattr(klass, attr) if not hasattr(attr_value, "__call__"): continue patcher = self.copy() setattr(klass, attr, patcher(attr_value)) return klass @contextlib.contextmanager def decoration_helper(self, patched, args, keywargs): extra_args = [] with contextlib.ExitStack() as exit_stack: for patching in patched.patchings: arg = exit_stack.enter_context(patching) if patching.attribute_name is not None: keywargs.update(arg) elif patching.new is DEFAULT: extra_args.append(arg) args += tuple(extra_args) yield (args, keywargs) def decorate_callable(self, func): # NB. Keep the method in sync with decorate_async_callable() if hasattr(func, 'patchings'): func.patchings.append(self) return func @wraps(func) def patched(*args, **keywargs): with self.decoration_helper(patched, args, keywargs) as (newargs, newkeywargs): return func(*newargs, **newkeywargs) patched.patchings = [self] return patched def decorate_async_callable(self, func): # NB. Keep the method in sync with decorate_callable() if hasattr(func, 'patchings'): func.patchings.append(self) return func @wraps(func) async def patched(*args, **keywargs): with self.decoration_helper(patched, args, keywargs) as (newargs, newkeywargs): return await func(*newargs, **newkeywargs) patched.patchings = [self] return patched def get_original(self): target = self.getter() name = self.attribute original = DEFAULT local = False try: original = target.__dict__[name] except (AttributeError, KeyError): original = getattr(target, name, DEFAULT) else: local = True if name in _builtins and isinstance(target, ModuleType): self.create = True if not self.create and original is DEFAULT: raise AttributeError( "%s does not have the attribute %r" % (target, name) ) return original, local def __enter__(self): """Perform the patch.""" new, spec, spec_set = self.new, self.spec, self.spec_set autospec, kwargs = self.autospec, self.kwargs new_callable = self.new_callable self.target = self.getter() # normalise False to None if spec is False: spec = None if spec_set is False: spec_set = None if autospec is False: autospec = None if spec is not None and autospec is not None: raise TypeError("Can't specify spec and autospec") if ((spec is not None or autospec is not None) and spec_set not in (True, None)): raise TypeError("Can't provide explicit spec_set *and* spec or autospec") original, local = self.get_original() if new is DEFAULT and autospec is None: inherit = False if spec is True: # set spec to the object we are replacing spec = original if spec_set is True: spec_set = original spec = None elif spec is not None: if spec_set is True: spec_set = spec spec = None elif spec_set is True: spec_set = original if spec is not None or spec_set is not None: if original is DEFAULT: raise TypeError("Can't use 'spec' with create=True") if isinstance(original, type): # If we're patching out a class and there is a spec inherit = True if spec is None and _is_async_obj(original): Klass = AsyncMock else: Klass = MagicMock _kwargs = {} if new_callable is not None: Klass = new_callable elif spec is not None or spec_set is not None: this_spec = spec if spec_set is not None: this_spec = spec_set if _is_list(this_spec): not_callable = '__call__' not in this_spec else: not_callable = not callable(this_spec) if _is_async_obj(this_spec): Klass = AsyncMock elif not_callable: Klass = NonCallableMagicMock if spec is not None: _kwargs['spec'] = spec if spec_set is not None: _kwargs['spec_set'] = spec_set # add a name to mocks if (isinstance(Klass, type) and issubclass(Klass, NonCallableMock) and self.attribute): _kwargs['name'] = self.attribute _kwargs.update(kwargs) new = Klass(**_kwargs) if inherit and _is_instance_mock(new): # we can only tell if the instance should be callable if the # spec is not a list this_spec = spec if spec_set is not None: this_spec = spec_set if (not _is_list(this_spec) and not _instance_callable(this_spec)): Klass = NonCallableMagicMock _kwargs.pop('name') new.return_value = Klass(_new_parent=new, _new_name='()', **_kwargs) elif autospec is not None: # spec is ignored, new *must* be default, spec_set is treated # as a boolean. Should we check spec is not None and that spec_set # is a bool? if new is not DEFAULT: raise TypeError( "autospec creates the mock for you. Can't specify " "autospec and new." ) if original is DEFAULT: raise TypeError("Can't use 'autospec' with create=True") spec_set = bool(spec_set) if autospec is True: autospec = original new = create_autospec(autospec, spec_set=spec_set, _name=self.attribute, **kwargs) elif kwargs: # can't set keyword args when we aren't creating the mock # XXXX If new is a Mock we could call new.configure_mock(**kwargs) raise TypeError("Can't pass kwargs to a mock we aren't creating") new_attr = new self.temp_original = original self.is_local = local self._exit_stack = contextlib.ExitStack() try: setattr(self.target, self.attribute, new_attr) if self.attribute_name is not None: extra_args = {} if self.new is DEFAULT: extra_args[self.attribute_name] = new for patching in self.additional_patchers: arg = self._exit_stack.enter_context(patching) if patching.new is DEFAULT: extra_args.update(arg) return extra_args return new except: if not self.__exit__(*sys.exc_info()): raise def __exit__(self, *exc_info): """Undo the patch.""" if self.is_local and self.temp_original is not DEFAULT: setattr(self.target, self.attribute, self.temp_original) else: delattr(self.target, self.attribute) if not self.create and (not hasattr(self.target, self.attribute) or self.attribute in ('__doc__', '__module__', '__defaults__', '__annotations__', '__kwdefaults__')): # needed for proxy objects like django settings setattr(self.target, self.attribute, self.temp_original) del self.temp_original del self.is_local del self.target exit_stack = self._exit_stack del self._exit_stack return exit_stack.__exit__(*exc_info) def start(self): """Activate a patch, returning any created mock.""" result = self.__enter__() self._active_patches.append(self) return result def stop(self): """Stop an active patch.""" try: self._active_patches.remove(self) except ValueError: # If the patch hasn't been started this will fail return None return self.__exit__(None, None, None) def _get_target(target): try: target, attribute = target.rsplit('.', 1) except (TypeError, ValueError): raise TypeError("Need a valid target to patch. You supplied: %r" % (target,)) getter = lambda: _importer(target) return getter, attribute def _patch_object( target, attribute, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs ): """ patch the named member (`attribute`) on an object (`target`) with a mock object. `patch.object` can be used as a decorator, class decorator or a context manager. Arguments `new`, `spec`, `create`, `spec_set`, `autospec` and `new_callable` have the same meaning as for `patch`. Like `patch`, `patch.object` takes arbitrary keyword arguments for configuring the mock object it creates. When used as a class decorator `patch.object` honours `patch.TEST_PREFIX` for choosing which methods to wrap. """ if type(target) is str: raise TypeError( f"{target!r} must be the actual object to be patched, not a str" ) getter = lambda: target return _patch( getter, attribute, new, spec, create, spec_set, autospec, new_callable, kwargs ) def _patch_multiple(target, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs): """Perform multiple patches in a single call. It takes the object to be patched (either as an object or a string to fetch the object by importing) and keyword arguments for the patches:: with patch.multiple(settings, FIRST_PATCH='one', SECOND_PATCH='two'): ... Use `DEFAULT` as the value if you want `patch.multiple` to create mocks for you. In this case the created mocks are passed into a decorated function by keyword, and a dictionary is returned when `patch.multiple` is used as a context manager. `patch.multiple` can be used as a decorator, class decorator or a context manager. The arguments `spec`, `spec_set`, `create`, `autospec` and `new_callable` have the same meaning as for `patch`. These arguments will be applied to *all* patches done by `patch.multiple`. When used as a class decorator `patch.multiple` honours `patch.TEST_PREFIX` for choosing which methods to wrap. """ if type(target) is str: getter = lambda: _importer(target) else: getter = lambda: target if not kwargs: raise ValueError( 'Must supply at least one keyword argument with patch.multiple' ) # need to wrap in a list for python 3, where items is a view items = list(kwargs.items()) attribute, new = items[0] patcher = _patch( getter, attribute, new, spec, create, spec_set, autospec, new_callable, {} ) patcher.attribute_name = attribute for attribute, new in items[1:]: this_patcher = _patch( getter, attribute, new, spec, create, spec_set, autospec, new_callable, {} ) this_patcher.attribute_name = attribute patcher.additional_patchers.append(this_patcher) return patcher def patch( target, new=DEFAULT, spec=None, create=False, spec_set=None, autospec=None, new_callable=None, **kwargs ): """ `patch` acts as a function decorator, class decorator or a context manager. Inside the body of the function or with statement, the `target` is patched with a `new` object. When the function/with statement exits the patch is undone. If `new` is omitted, then the target is replaced with an `AsyncMock if the patched object is an async function or a `MagicMock` otherwise. If `patch` is used as a decorator and `new` is omitted, the created mock is passed in as an extra argument to the decorated function. If `patch` is used as a context manager the created mock is returned by the context manager. `target` should be a string in the form `'package.module.ClassName'`. The `target` is imported and the specified object replaced with the `new` object, so the `target` must be importable from the environment you are calling `patch` from. The target is imported when the decorated function is executed, not at decoration time. The `spec` and `spec_set` keyword arguments are passed to the `MagicMock` if patch is creating one for you. In addition you can pass `spec=True` or `spec_set=True`, which causes patch to pass in the object being mocked as the spec/spec_set object. `new_callable` allows you to specify a different class, or callable object, that will be called to create the `new` object. By default `AsyncMock` is used for async functions and `MagicMock` for the rest. A more powerful form of `spec` is `autospec`. If you set `autospec=True` then the mock will be created with a spec from the object being replaced. All attributes of the mock will also have the spec of the corresponding attribute of the object being replaced. Methods and functions being mocked will have their arguments checked and will raise a `TypeError` if they are called with the wrong signature. For mocks replacing a class, their return value (the 'instance') will have the same spec as the class. Instead of `autospec=True` you can pass `autospec=some_object` to use an arbitrary object as the spec instead of the one being replaced. By default `patch` will fail to replace attributes that don't exist. If you pass in `create=True`, and the attribute doesn't exist, patch will create the attribute for you when the patched function is called, and delete it again afterwards. This is useful for writing tests against attributes that your production code creates at runtime. It is off by default because it can be dangerous. With it switched on you can write passing tests against APIs that don't actually exist! Patch can be used as a `TestCase` class decorator. It works by decorating each test method in the class. This reduces the boilerplate code when your test methods share a common patchings set. `patch` finds tests by looking for method names that start with `patch.TEST_PREFIX`. By default this is `test`, which matches the way `unittest` finds tests. You can specify an alternative prefix by setting `patch.TEST_PREFIX`. Patch can be used as a context manager, with the with statement. Here the patching applies to the indented block after the with statement. If you use "as" then the patched object will be bound to the name after the "as"; very useful if `patch` is creating a mock object for you. `patch` takes arbitrary keyword arguments. These will be passed to `AsyncMock` if the patched object is asynchronous, to `MagicMock` otherwise or to `new_callable` if specified. `patch.dict(...)`, `patch.multiple(...)` and `patch.object(...)` are available for alternate use-cases. """ getter, attribute = _get_target(target) return _patch( getter, attribute, new, spec, create, spec_set, autospec, new_callable, kwargs ) class _patch_dict(object): """ Patch a dictionary, or dictionary like object, and restore the dictionary to its original state after the test. `in_dict` can be a dictionary or a mapping like container. If it is a mapping then it must at least support getting, setting and deleting items plus iterating over keys. `in_dict` can also be a string specifying the name of the dictionary, which will then be fetched by importing it. `values` can be a dictionary of values to set in the dictionary. `values` can also be an iterable of `(key, value)` pairs. If `clear` is True then the dictionary will be cleared before the new values are set. `patch.dict` can also be called with arbitrary keyword arguments to set values in the dictionary:: with patch.dict('sys.modules', mymodule=Mock(), other_module=Mock()): ... `patch.dict` can be used as a context manager, decorator or class decorator. When used as a class decorator `patch.dict` honours `patch.TEST_PREFIX` for choosing which methods to wrap. """ def __init__(self, in_dict, values=(), clear=False, **kwargs): self.in_dict = in_dict # support any argument supported by dict(...) constructor self.values = dict(values) self.values.update(kwargs) self.clear = clear self._original = None def __call__(self, f): if isinstance(f, type): return self.decorate_class(f) @wraps(f) def _inner(*args, **kw): self._patch_dict() try: return f(*args, **kw) finally: self._unpatch_dict() return _inner def decorate_class(self, klass): for attr in dir(klass): attr_value = getattr(klass, attr) if (attr.startswith(patch.TEST_PREFIX) and hasattr(attr_value, "__call__")): decorator = _patch_dict(self.in_dict, self.values, self.clear) decorated = decorator(attr_value) setattr(klass, attr, decorated) return klass def __enter__(self): """Patch the dict.""" self._patch_dict() return self.in_dict def _patch_dict(self): values = self.values if isinstance(self.in_dict, str): self.in_dict = _importer(self.in_dict) in_dict = self.in_dict clear = self.clear try: original = in_dict.copy() except AttributeError: # dict like object with no copy method # must support iteration over keys original = {} for key in in_dict: original[key] = in_dict[key] self._original = original if clear: _clear_dict(in_dict) try: in_dict.update(values) except AttributeError: # dict like object with no update method for key in values: in_dict[key] = values[key] def _unpatch_dict(self): in_dict = self.in_dict original = self._original _clear_dict(in_dict) try: in_dict.update(original) except AttributeError: for key in original: in_dict[key] = original[key] def __exit__(self, *args): """Unpatch the dict.""" if self._original is not None: self._unpatch_dict() return False def start(self): """Activate a patch, returning any created mock.""" result = self.__enter__() _patch._active_patches.append(self) return result def stop(self): """Stop an active patch.""" try: _patch._active_patches.remove(self) except ValueError: # If the patch hasn't been started this will fail return None return self.__exit__(None, None, None) def _clear_dict(in_dict): try: in_dict.clear() except AttributeError: keys = list(in_dict) for key in keys: del in_dict[key] def _patch_stopall(): """Stop all active patches. LIFO to unroll nested patches.""" for patch in reversed(_patch._active_patches): patch.stop() patch.object = _patch_object patch.dict = _patch_dict patch.multiple = _patch_multiple patch.stopall = _patch_stopall patch.TEST_PREFIX = 'test' magic_methods = ( "lt le gt ge eq ne " "getitem setitem delitem " "len contains iter " "hash str sizeof " "enter exit " # we added divmod and rdivmod here instead of numerics # because there is no idivmod "divmod rdivmod neg pos abs invert " "complex int float index " "round trunc floor ceil " "bool next " "fspath " "aiter " ) if IS_PYPY: # PyPy has no __sizeof__: http://doc.pypy.org/en/latest/cpython_differences.html magic_methods = magic_methods.replace('sizeof ', '') numerics = ( "add sub mul matmul div floordiv mod lshift rshift and xor or pow truediv" ) inplace = ' '.join('i%s' % n for n in numerics.split()) right = ' '.join('r%s' % n for n in numerics.split()) # not including __prepare__, __instancecheck__, __subclasscheck__ # (as they are metaclass methods) # __del__ is not supported at all as it causes problems if it exists _non_defaults = { '__get__', '__set__', '__delete__', '__reversed__', '__missing__', '__reduce__', '__reduce_ex__', '__getinitargs__', '__getnewargs__', '__getstate__', '__setstate__', '__getformat__', '__setformat__', '__repr__', '__dir__', '__subclasses__', '__format__', '__getnewargs_ex__', } def _get_method(name, func): "Turns a callable object (like a mock) into a real function" def method(self, *args, **kw): return func(self, *args, **kw) method.__name__ = name return method _magics = { '__%s__' % method for method in ' '.join([magic_methods, numerics, inplace, right]).split() } # Magic methods used for async `with` statements _async_method_magics = {"__aenter__", "__aexit__", "__anext__"} # Magic methods that are only used with async calls but are synchronous functions themselves _sync_async_magics = {"__aiter__"} _async_magics = _async_method_magics | _sync_async_magics _all_sync_magics = _magics | _non_defaults _all_magics = _all_sync_magics | _async_magics _unsupported_magics = { '__getattr__', '__setattr__', '__init__', '__new__', '__prepare__', '__instancecheck__', '__subclasscheck__', '__del__' } _calculate_return_value = { '__hash__': lambda self: object.__hash__(self), '__str__': lambda self: object.__str__(self), '__sizeof__': lambda self: object.__sizeof__(self), '__fspath__': lambda self: f"{type(self).__name__}/{self._extract_mock_name()}/{id(self)}", } _return_values = { '__lt__': NotImplemented, '__gt__': NotImplemented, '__le__': NotImplemented, '__ge__': NotImplemented, '__int__': 1, '__contains__': False, '__len__': 0, '__exit__': False, '__complex__': 1j, '__float__': 1.0, '__bool__': True, '__index__': 1, '__aexit__': False, } def _get_eq(self): def __eq__(other): ret_val = self.__eq__._mock_return_value if ret_val is not DEFAULT: return ret_val if self is other: return True return NotImplemented return __eq__ def _get_ne(self): def __ne__(other): if self.__ne__._mock_return_value is not DEFAULT: return DEFAULT if self is other: return False return NotImplemented return __ne__ def _get_iter(self): def __iter__(): ret_val = self.__iter__._mock_return_value if ret_val is DEFAULT: return iter([]) # if ret_val was already an iterator, then calling iter on it should # return the iterator unchanged return iter(ret_val) return __iter__ def _get_async_iter(self): def __aiter__(): ret_val = self.__aiter__._mock_return_value if ret_val is DEFAULT: return _AsyncIterator(iter([])) return _AsyncIterator(iter(ret_val)) return __aiter__ _side_effect_methods = { '__eq__': _get_eq, '__ne__': _get_ne, '__iter__': _get_iter, '__aiter__': _get_async_iter } def _set_return_value(mock, method, name): fixed = _return_values.get(name, DEFAULT) if fixed is not DEFAULT: method.return_value = fixed return return_calculator = _calculate_return_value.get(name) if return_calculator is not None: return_value = return_calculator(mock) method.return_value = return_value return side_effector = _side_effect_methods.get(name) if side_effector is not None: method.side_effect = side_effector(mock) class MagicMixin(Base): def __init__(self, *args, **kw): self._mock_set_magics() # make magic work for kwargs in init _safe_super(MagicMixin, self).__init__(*args, **kw) self._mock_set_magics() # fix magic broken by upper level init def _mock_set_magics(self): orig_magics = _magics | _async_method_magics these_magics = orig_magics if getattr(self, "_mock_methods", None) is not None: these_magics = orig_magics.intersection(self._mock_methods) remove_magics = set() remove_magics = orig_magics - these_magics for entry in remove_magics: if entry in type(self).__dict__: # remove unneeded magic methods delattr(self, entry) # don't overwrite existing attributes if called a second time these_magics = these_magics - set(type(self).__dict__) _type = type(self) for entry in these_magics: setattr(_type, entry, MagicProxy(entry, self)) class NonCallableMagicMock(MagicMixin, NonCallableMock): """A version of `MagicMock` that isn't callable.""" def mock_add_spec(self, spec, spec_set=False): """Add a spec to a mock. `spec` can either be an object or a list of strings. Only attributes on the `spec` can be fetched as attributes from the mock. If `spec_set` is True then only attributes on the spec can be set.""" self._mock_add_spec(spec, spec_set) self._mock_set_magics() class AsyncMagicMixin(MagicMixin): def __init__(self, *args, **kw): self._mock_set_magics() # make magic work for kwargs in init _safe_super(AsyncMagicMixin, self).__init__(*args, **kw) self._mock_set_magics() # fix magic broken by upper level init class MagicMock(MagicMixin, Mock): """ MagicMock is a subclass of Mock with default implementations of most of the magic methods. You can use MagicMock without having to configure the magic methods yourself. If you use the `spec` or `spec_set` arguments then *only* magic methods that exist in the spec will be created. Attributes and the return value of a `MagicMock` will also be `MagicMocks`. """ def mock_add_spec(self, spec, spec_set=False): """Add a spec to a mock. `spec` can either be an object or a list of strings. Only attributes on the `spec` can be fetched as attributes from the mock. If `spec_set` is True then only attributes on the spec can be set.""" self._mock_add_spec(spec, spec_set) self._mock_set_magics() class MagicProxy(Base): def __init__(self, name, parent): self.name = name self.parent = parent def create_mock(self): entry = self.name parent = self.parent m = parent._get_child_mock(name=entry, _new_name=entry, _new_parent=parent) setattr(parent, entry, m) _set_return_value(parent, m, entry) return m def __get__(self, obj, _type=None): return self.create_mock() class AsyncMockMixin(Base): await_count = _delegating_property('await_count') await_args = _delegating_property('await_args') await_args_list = _delegating_property('await_args_list') def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # iscoroutinefunction() checks _is_coroutine property to say if an # object is a coroutine. Without this check it looks to see if it is a # function/method, which in this case it is not (since it is an # AsyncMock). # It is set through __dict__ because when spec_set is True, this # attribute is likely undefined. self.__dict__['_is_coroutine'] = asyncio.coroutines._is_coroutine self.__dict__['_mock_await_count'] = 0 self.__dict__['_mock_await_args'] = None self.__dict__['_mock_await_args_list'] = _CallList() code_mock = NonCallableMock(spec_set=CodeType) code_mock.co_flags = inspect.CO_COROUTINE self.__dict__['__code__'] = code_mock async def _execute_mock_call(_mock_self, *args, **kwargs): self = _mock_self # This is nearly just like super(), except for special handling # of coroutines _call = _Call((args, kwargs), two=True) self.await_count += 1 self.await_args = _call self.await_args_list.append(_call) effect = self.side_effect if effect is not None: if _is_exception(effect): raise effect elif not _callable(effect): try: result = next(effect) except StopIteration: # It is impossible to propogate a StopIteration # through coroutines because of PEP 479 raise StopAsyncIteration if _is_exception(result): raise result elif iscoroutinefunction(effect): result = await effect(*args, **kwargs) else: result = effect(*args, **kwargs) if result is not DEFAULT: return result if self._mock_return_value is not DEFAULT: return self.return_value if self._mock_wraps is not None: if iscoroutinefunction(self._mock_wraps): return await self._mock_wraps(*args, **kwargs) return self._mock_wraps(*args, **kwargs) return self.return_value def assert_awaited(_mock_self): """ Assert that the mock was awaited at least once. """ self = _mock_self if self.await_count == 0: msg = f"Expected {self._mock_name or 'mock'} to have been awaited." raise AssertionError(msg) def assert_awaited_once(_mock_self): """ Assert that the mock was awaited exactly once. """ self = _mock_self if not self.await_count == 1: msg = (f"Expected {self._mock_name or 'mock'} to have been awaited once." f" Awaited {self.await_count} times.") raise AssertionError(msg) def assert_awaited_with(_mock_self, *args, **kwargs): """ Assert that the last await was with the specified arguments. """ self = _mock_self if self.await_args is None: expected = self._format_mock_call_signature(args, kwargs) raise AssertionError(f'Expected await: {expected}\nNot awaited') def _error_message(): msg = self._format_mock_failure_message(args, kwargs, action='await') return msg expected = self._call_matcher(_Call((args, kwargs), two=True)) actual = self._call_matcher(self.await_args) if actual != expected: cause = expected if isinstance(expected, Exception) else None raise AssertionError(_error_message()) from cause def assert_awaited_once_with(_mock_self, *args, **kwargs): """ Assert that the mock was awaited exactly once and with the specified arguments. """ self = _mock_self if not self.await_count == 1: msg = (f"Expected {self._mock_name or 'mock'} to have been awaited once." f" Awaited {self.await_count} times.") raise AssertionError(msg) return self.assert_awaited_with(*args, **kwargs) def assert_any_await(_mock_self, *args, **kwargs): """ Assert the mock has ever been awaited with the specified arguments. """ self = _mock_self expected = self._call_matcher(_Call((args, kwargs), two=True)) cause = expected if isinstance(expected, Exception) else None actual = [self._call_matcher(c) for c in self.await_args_list] if cause or expected not in _AnyComparer(actual): expected_string = self._format_mock_call_signature(args, kwargs) raise AssertionError( '%s await not found' % expected_string ) from cause def assert_has_awaits(_mock_self, calls, any_order=False): """ Assert the mock has been awaited with the specified calls. The :attr:`await_args_list` list is checked for the awaits. If `any_order` is False (the default) then the awaits must be sequential. There can be extra calls before or after the specified awaits. If `any_order` is True then the awaits can be in any order, but they must all appear in :attr:`await_args_list`. """ self = _mock_self expected = [self._call_matcher(c) for c in calls] cause = cause = next((e for e in expected if isinstance(e, Exception)), None) all_awaits = _CallList(self._call_matcher(c) for c in self.await_args_list) if not any_order: if expected not in all_awaits: if cause is None: problem = 'Awaits not found.' else: problem = ('Error processing expected awaits.\n' 'Errors: {}').format( [e if isinstance(e, Exception) else None for e in expected]) raise AssertionError( f'{problem}\n' f'Expected: {_CallList(calls)}\n' f'Actual: {self.await_args_list}' ) from cause return all_awaits = list(all_awaits) not_found = [] for kall in expected: try: all_awaits.remove(kall) except ValueError: not_found.append(kall) if not_found: raise AssertionError( '%r not all found in await list' % (tuple(not_found),) ) from cause def assert_not_awaited(_mock_self): """ Assert that the mock was never awaited. """ self = _mock_self if self.await_count != 0: msg = (f"Expected {self._mock_name or 'mock'} to not have been awaited." f" Awaited {self.await_count} times.") raise AssertionError(msg) def reset_mock(self, *args, **kwargs): """ See :func:`.Mock.reset_mock()` """ super().reset_mock(*args, **kwargs) self.await_count = 0 self.await_args = None self.await_args_list = _CallList() class AsyncMock(AsyncMockMixin, AsyncMagicMixin, Mock): """ Enhance :class:`Mock` with features allowing to mock an async function. The :class:`AsyncMock` object will behave so the object is recognized as an async function, and the result of a call is an awaitable: >>> mock = AsyncMock() >>> iscoroutinefunction(mock) True >>> inspect.isawaitable(mock()) True The result of ``mock()`` is an async function which will have the outcome of ``side_effect`` or ``return_value``: - if ``side_effect`` is a function, the async function will return the result of that function, - if ``side_effect`` is an exception, the async function will raise the exception, - if ``side_effect`` is an iterable, the async function will return the next value of the iterable, however, if the sequence of result is exhausted, ``StopIteration`` is raised immediately, - if ``side_effect`` is not defined, the async function will return the value defined by ``return_value``, hence, by default, the async function returns a new :class:`AsyncMock` object. If the outcome of ``side_effect`` or ``return_value`` is an async function, the mock async function obtained when the mock object is called will be this async function itself (and not an async function returning an async function). The test author can also specify a wrapped object with ``wraps``. In this case, the :class:`Mock` object behavior is the same as with an :class:`.Mock` object: the wrapped object may have methods defined as async function functions. Based on Martin Richard's asynctest project. """ class _ANY(object): "A helper object that compares equal to everything." def __eq__(self, other): return True def __ne__(self, other): return False def __repr__(self): return '' ANY = _ANY() def _format_call_signature(name, args, kwargs): message = '%s(%%s)' % name formatted_args = '' args_string = ', '.join([repr(arg) for arg in args]) kwargs_string = ', '.join([ '%s=%r' % (key, value) for key, value in kwargs.items() ]) if args_string: formatted_args = args_string if kwargs_string: if formatted_args: formatted_args += ', ' formatted_args += kwargs_string return message % formatted_args class _Call(tuple): """ A tuple for holding the results of a call to a mock, either in the form `(args, kwargs)` or `(name, args, kwargs)`. If args or kwargs are empty then a call tuple will compare equal to a tuple without those values. This makes comparisons less verbose:: _Call(('name', (), {})) == ('name',) _Call(('name', (1,), {})) == ('name', (1,)) _Call(((), {'a': 'b'})) == ({'a': 'b'},) The `_Call` object provides a useful shortcut for comparing with call:: _Call(((1, 2), {'a': 3})) == call(1, 2, a=3) _Call(('foo', (1, 2), {'a': 3})) == call.foo(1, 2, a=3) If the _Call has no name then it will match any name. """ def __new__(cls, value=(), name='', parent=None, two=False, from_kall=True): args = () kwargs = {} _len = len(value) if _len == 3: name, args, kwargs = value elif _len == 2: first, second = value if isinstance(first, str): name = first if isinstance(second, tuple): args = second else: kwargs = second else: args, kwargs = first, second elif _len == 1: value, = value if isinstance(value, str): name = value elif isinstance(value, tuple): args = value else: kwargs = value if two: return tuple.__new__(cls, (args, kwargs)) return tuple.__new__(cls, (name, args, kwargs)) def __init__(self, value=(), name=None, parent=None, two=False, from_kall=True): self._mock_name = name self._mock_parent = parent self._mock_from_kall = from_kall def __eq__(self, other): try: len_other = len(other) except TypeError: return NotImplemented self_name = '' if len(self) == 2: self_args, self_kwargs = self else: self_name, self_args, self_kwargs = self if (getattr(self, '_mock_parent', None) and getattr(other, '_mock_parent', None) and self._mock_parent != other._mock_parent): return False other_name = '' if len_other == 0: other_args, other_kwargs = (), {} elif len_other == 3: other_name, other_args, other_kwargs = other elif len_other == 1: value, = other if isinstance(value, tuple): other_args = value other_kwargs = {} elif isinstance(value, str): other_name = value other_args, other_kwargs = (), {} else: other_args = () other_kwargs = value elif len_other == 2: # could be (name, args) or (name, kwargs) or (args, kwargs) first, second = other if isinstance(first, str): other_name = first if isinstance(second, tuple): other_args, other_kwargs = second, {} else: other_args, other_kwargs = (), second else: other_args, other_kwargs = first, second else: return False if self_name and other_name != self_name: return False # this order is important for ANY to work! return (other_args, other_kwargs) == (self_args, self_kwargs) __ne__ = object.__ne__ def __call__(self, *args, **kwargs): if self._mock_name is None: return _Call(('', args, kwargs), name='()') name = self._mock_name + '()' return _Call((self._mock_name, args, kwargs), name=name, parent=self) def __getattr__(self, attr): if self._mock_name is None: return _Call(name=attr, from_kall=False) name = '%s.%s' % (self._mock_name, attr) return _Call(name=name, parent=self, from_kall=False) def __getattribute__(self, attr): if attr in tuple.__dict__: raise AttributeError return tuple.__getattribute__(self, attr) def _get_call_arguments(self): if len(self) == 2: args, kwargs = self else: name, args, kwargs = self return args, kwargs @property def args(self): return self._get_call_arguments()[0] @property def kwargs(self): return self._get_call_arguments()[1] def __repr__(self): if not self._mock_from_kall: name = self._mock_name or 'call' if name.startswith('()'): name = 'call%s' % name return name if len(self) == 2: name = 'call' args, kwargs = self else: name, args, kwargs = self if not name: name = 'call' elif not name.startswith('()'): name = 'call.%s' % name else: name = 'call%s' % name return _format_call_signature(name, args, kwargs) def call_list(self): """For a call object that represents multiple calls, `call_list` returns a list of all the intermediate calls as well as the final call.""" vals = [] thing = self while thing is not None: if thing._mock_from_kall: vals.append(thing) thing = thing._mock_parent return _CallList(reversed(vals)) call = _Call(from_kall=False) def create_autospec(spec, spec_set=False, instance=False, _parent=None, _name=None, **kwargs): """Create a mock object using another object as a spec. Attributes on the mock will use the corresponding attribute on the `spec` object as their spec. Functions or methods being mocked will have their arguments checked to check that they are called with the correct signature. If `spec_set` is True then attempting to set attributes that don't exist on the spec object will raise an `AttributeError`. If a class is used as a spec then the return value of the mock (the instance of the class) will have the same spec. You can use a class as the spec for an instance object by passing `instance=True`. The returned mock will only be callable if instances of the mock are callable. `create_autospec` also takes arbitrary keyword arguments that are passed to the constructor of the created mock.""" if _is_list(spec): # can't pass a list instance to the mock constructor as it will be # interpreted as a list of strings spec = type(spec) is_type = isinstance(spec, type) is_async_func = _is_async_func(spec) _kwargs = {'spec': spec} if spec_set: _kwargs = {'spec_set': spec} elif spec is None: # None we mock with a normal mock without a spec _kwargs = {} if _kwargs and instance: _kwargs['_spec_as_instance'] = True _kwargs.update(kwargs) Klass = MagicMock if inspect.isdatadescriptor(spec): # descriptors don't have a spec # because we don't know what type they return _kwargs = {} elif is_async_func: if instance: raise RuntimeError("Instance can not be True when create_autospec " "is mocking an async function") Klass = AsyncMock elif not _callable(spec): Klass = NonCallableMagicMock elif is_type and instance and not _instance_callable(spec): Klass = NonCallableMagicMock _name = _kwargs.pop('name', _name) _new_name = _name if _parent is None: # for a top level object no _new_name should be set _new_name = '' mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name, name=_name, **_kwargs) if isinstance(spec, FunctionTypes): # should only happen at the top level because we don't # recurse for functions mock = _set_signature(mock, spec) if is_async_func: _setup_async_mock(mock) else: _check_signature(spec, mock, is_type, instance) if _parent is not None and not instance: _parent._mock_children[_name] = mock if is_type and not instance and 'return_value' not in kwargs: mock.return_value = create_autospec(spec, spec_set, instance=True, _name='()', _parent=mock) for entry in dir(spec): if _is_magic(entry): # MagicMock already does the useful magic methods for us continue # XXXX do we need a better way of getting attributes without # triggering code execution (?) Probably not - we need the actual # object to mock it so we would rather trigger a property than mock # the property descriptor. Likewise we want to mock out dynamically # provided attributes. # XXXX what about attributes that raise exceptions other than # AttributeError on being fetched? # we could be resilient against it, or catch and propagate the # exception when the attribute is fetched from the mock try: original = getattr(spec, entry) except AttributeError: continue kwargs = {'spec': original} if spec_set: kwargs = {'spec_set': original} if not isinstance(original, FunctionTypes): new = _SpecState(original, spec_set, mock, entry, instance) mock._mock_children[entry] = new else: parent = mock if isinstance(spec, FunctionTypes): parent = mock.mock skipfirst = _must_skip(spec, entry, is_type) kwargs['_eat_self'] = skipfirst if iscoroutinefunction(original): child_klass = AsyncMock else: child_klass = MagicMock new = child_klass(parent=parent, name=entry, _new_name=entry, _new_parent=parent, **kwargs) mock._mock_children[entry] = new _check_signature(original, new, skipfirst=skipfirst) # so functions created with _set_signature become instance attributes, # *plus* their underlying mock exists in _mock_children of the parent # mock. Adding to _mock_children may be unnecessary where we are also # setting as an instance attribute? if isinstance(new, FunctionTypes): setattr(mock, entry, new) return mock def _must_skip(spec, entry, is_type): """ Return whether we should skip the first argument on spec's `entry` attribute. """ if not isinstance(spec, type): if entry in getattr(spec, '__dict__', {}): # instance attribute - shouldn't skip return False spec = spec.__class__ for klass in spec.__mro__: result = klass.__dict__.get(entry, DEFAULT) if result is DEFAULT: continue if isinstance(result, (staticmethod, classmethod)): return False elif isinstance(result, FunctionTypes): # Normal method => skip if looked up on type # (if looked up on instance, self is already skipped) return is_type else: return False # function is a dynamically provided attribute return is_type class _SpecState(object): def __init__(self, spec, spec_set=False, parent=None, name=None, ids=None, instance=False): self.spec = spec self.ids = ids self.spec_set = spec_set self.parent = parent self.instance = instance self.name = name FunctionTypes = ( # python function type(create_autospec), # instance method type(ANY.__eq__), ) file_spec = None def _to_stream(read_data): if isinstance(read_data, bytes): return io.BytesIO(read_data) else: return io.StringIO(read_data) def mock_open(mock=None, read_data=''): """ A helper function to create a mock to replace the use of `open`. It works for `open` called directly or used as a context manager. The `mock` argument is the mock object to configure. If `None` (the default) then a `MagicMock` will be created for you, with the API limited to methods or attributes available on standard file handles. `read_data` is a string for the `read`, `readline` and `readlines` of the file handle to return. This is an empty string by default. """ _read_data = _to_stream(read_data) _state = [_read_data, None] def _readlines_side_effect(*args, **kwargs): if handle.readlines.return_value is not None: return handle.readlines.return_value return _state[0].readlines(*args, **kwargs) def _read_side_effect(*args, **kwargs): if handle.read.return_value is not None: return handle.read.return_value return _state[0].read(*args, **kwargs) def _readline_side_effect(*args, **kwargs): yield from _iter_side_effect() while True: yield _state[0].readline(*args, **kwargs) def _iter_side_effect(): if handle.readline.return_value is not None: while True: yield handle.readline.return_value for line in _state[0]: yield line def _next_side_effect(): if handle.readline.return_value is not None: return handle.readline.return_value return next(_state[0]) global file_spec if file_spec is None: import _io file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO)))) if mock is None: mock = MagicMock(name='open', spec=open) handle = MagicMock(spec=file_spec) handle.__enter__.return_value = handle handle.write.return_value = None handle.read.return_value = None handle.readline.return_value = None handle.readlines.return_value = None handle.read.side_effect = _read_side_effect _state[1] = _readline_side_effect() handle.readline.side_effect = _state[1] handle.readlines.side_effect = _readlines_side_effect handle.__iter__.side_effect = _iter_side_effect handle.__next__.side_effect = _next_side_effect def reset_data(*args, **kwargs): _state[0] = _to_stream(read_data) if handle.readline.side_effect == _state[1]: # Only reset the side effect if the user hasn't overridden it. _state[1] = _readline_side_effect() handle.readline.side_effect = _state[1] return DEFAULT mock.side_effect = reset_data mock.return_value = handle return mock class PropertyMock(Mock): """ A mock intended to be used as a property, or other descriptor, on a class. `PropertyMock` provides `__get__` and `__set__` methods so you can specify a return value when it is fetched. Fetching a `PropertyMock` instance from an object calls the mock, with no args. Setting it calls the mock with the value being set. """ def _get_child_mock(self, **kwargs): return MagicMock(**kwargs) def __get__(self, obj, obj_type=None): return self() def __set__(self, obj, val): self(val) def seal(mock): """Disable the automatic generation of child mocks. Given an input Mock, seals it to ensure no further mocks will be generated when accessing an attribute that was not already defined. The operation recursively seals the mock passed in, meaning that the mock itself, any mocks generated by accessing one of its attributes, and all assigned mocks without a name or spec will be sealed. """ mock._mock_sealed = True for attr in dir(mock): try: m = getattr(mock, attr) except AttributeError: continue if not isinstance(m, NonCallableMock): continue if m._mock_new_parent is mock: seal(m) class _AsyncIterator: """ Wraps an iterator in an asynchronous iterator. """ def __init__(self, iterator): self.iterator = iterator code_mock = NonCallableMock(spec_set=CodeType) code_mock.co_flags = inspect.CO_ITERABLE_COROUTINE self.__dict__['__code__'] = code_mock async def __anext__(self): try: return next(self.iterator) except StopIteration: pass raise StopAsyncIteration mock-4.0.3/mock/tests/000077500000000000000000000000001376434722300145555ustar00rootroot00000000000000mock-4.0.3/mock/tests/__init__.py000066400000000000000000000000001376434722300166540ustar00rootroot00000000000000mock-4.0.3/mock/tests/support.py000066400000000000000000000017161376434722300166500ustar00rootroot00000000000000import contextlib import sys target = {'foo': 'FOO'} def is_instance(obj, klass): """Version of is_instance that doesn't access __class__""" return issubclass(type(obj), klass) class SomeClass(object): class_attribute = None def wibble(self): pass class X(object): pass @contextlib.contextmanager def uncache(*names): """Uncache a module from sys.modules. A basic sanity check is performed to prevent uncaching modules that either cannot/shouldn't be uncached. """ for name in names: assert name not in ('sys', 'marshal', 'imp') try: del sys.modules[name] except KeyError: pass try: yield finally: for name in names: del sys.modules[name] class _ALWAYS_EQ: """ Object that is equal to anything. """ def __eq__(self, other): return True def __ne__(self, other): return False ALWAYS_EQ = _ALWAYS_EQ() mock-4.0.3/mock/tests/testasync.py000066400000000000000000001112371376434722300171510ustar00rootroot00000000000000 import asyncio import gc import inspect import re import unittest from contextlib import contextmanager from mock import (ANY, call, AsyncMock, patch, MagicMock, Mock, create_autospec, sentinel) from mock.backports import IsolatedAsyncioTestCase, iscoroutinefunction from mock.mock import _CallList try: from asyncio import run except ImportError: def run(main): loop = asyncio.new_event_loop() try: return_value = loop.run_until_complete(main) finally: loop.close() return return_value def tearDownModule(): asyncio.set_event_loop_policy(None) class AsyncClass: def __init__(self): pass async def async_method(self): pass def normal_method(self): pass @classmethod async def async_class_method(cls): pass @staticmethod async def async_static_method(): pass class AwaitableClass: def __await__(self): yield async def async_func(): pass async def async_func_args(a, b, *, c): pass def normal_func(): pass class NormalClass(object): def a(self): pass async_foo_name = f'{__name__}.AsyncClass' normal_foo_name = f'{__name__}.NormalClass' @contextmanager def assertNeverAwaited(test): with test.assertWarnsRegex(RuntimeWarning, "was never awaited$"): yield # In non-CPython implementations of Python, this is needed because timely # deallocation is not guaranteed by the garbage collector. gc.collect() class AsyncPatchDecoratorTest(unittest.TestCase): def test_is_coroutine_function_patch(self): @patch.object(AsyncClass, 'async_method') def test_async(mock_method): self.assertTrue(iscoroutinefunction(mock_method)) test_async() def test_is_async_patch(self): @patch.object(AsyncClass, 'async_method') def test_async(mock_method): m = mock_method() self.assertTrue(inspect.isawaitable(m)) run(m) @patch(f'{async_foo_name}.async_method') def test_no_parent_attribute(mock_method): m = mock_method() self.assertTrue(inspect.isawaitable(m)) run(m) test_async() test_no_parent_attribute() def test_is_AsyncMock_patch(self): @patch.object(AsyncClass, 'async_method') def test_async(mock_method): self.assertIsInstance(mock_method, AsyncMock) test_async() def test_is_AsyncMock_patch_staticmethod(self): @patch.object(AsyncClass, 'async_static_method') def test_async(mock_method): self.assertIsInstance(mock_method, AsyncMock) test_async() def test_is_AsyncMock_patch_classmethod(self): @patch.object(AsyncClass, 'async_class_method') def test_async(mock_method): self.assertIsInstance(mock_method, AsyncMock) test_async() def test_async_def_patch(self): @patch(f"{__name__}.async_func", return_value=1) @patch(f"{__name__}.async_func_args", return_value=2) async def test_async(func_args_mock, func_mock): self.assertEqual(func_args_mock._mock_name, "async_func_args") self.assertEqual(func_mock._mock_name, "async_func") self.assertIsInstance(async_func, AsyncMock) self.assertIsInstance(async_func_args, AsyncMock) self.assertEqual(await async_func(), 1) self.assertEqual(await async_func_args(1, 2, c=3), 2) run(test_async()) self.assertTrue(inspect.iscoroutinefunction(async_func)) class AsyncPatchCMTest(unittest.TestCase): def test_is_async_function_cm(self): def test_async(): with patch.object(AsyncClass, 'async_method') as mock_method: self.assertTrue(iscoroutinefunction(mock_method)) test_async() def test_is_async_cm(self): def test_async(): with patch.object(AsyncClass, 'async_method') as mock_method: m = mock_method() self.assertTrue(inspect.isawaitable(m)) run(m) test_async() def test_is_AsyncMock_cm(self): def test_async(): with patch.object(AsyncClass, 'async_method') as mock_method: self.assertIsInstance(mock_method, AsyncMock) test_async() def test_async_def_cm(self): async def test_async(): with patch(f"{__name__}.async_func", AsyncMock()): self.assertIsInstance(async_func, AsyncMock) self.assertTrue(inspect.iscoroutinefunction(async_func)) run(test_async()) class AsyncMockTest(unittest.TestCase): def test_iscoroutinefunction_default(self): mock = AsyncMock() self.assertTrue(iscoroutinefunction(mock)) def test_iscoroutinefunction_function(self): async def foo(): pass mock = AsyncMock(foo) self.assertTrue(iscoroutinefunction(mock)) self.assertTrue(inspect.iscoroutinefunction(mock)) def test_isawaitable(self): mock = AsyncMock() m = mock() self.assertTrue(inspect.isawaitable(m)) run(m) self.assertIn('assert_awaited', dir(mock)) def test_iscoroutinefunction_normal_function(self): def foo(): pass mock = AsyncMock(foo) self.assertTrue(iscoroutinefunction(mock)) self.assertTrue(inspect.iscoroutinefunction(mock)) def test_future_isfuture(self): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) fut = asyncio.Future() loop.stop() loop.close() mock = AsyncMock(fut) self.assertIsInstance(mock, asyncio.Future) class AsyncAutospecTest(unittest.TestCase): def test_is_AsyncMock_patch(self): @patch(async_foo_name, autospec=True) def test_async(mock_method): self.assertIsInstance(mock_method.async_method, AsyncMock) self.assertIsInstance(mock_method, MagicMock) @patch(async_foo_name, autospec=True) def test_normal_method(mock_method): self.assertIsInstance(mock_method.normal_method, MagicMock) test_async() test_normal_method() def test_create_autospec_instance(self): with self.assertRaises(RuntimeError): create_autospec(async_func, instance=True) def test_create_autospec_awaitable_class(self): awaitable_mock = create_autospec(spec=AwaitableClass()) self.assertIsInstance(create_autospec(awaitable_mock), AsyncMock) def test_create_autospec(self): spec = create_autospec(async_func_args) awaitable = spec(1, 2, c=3) async def main(): await awaitable self.assertEqual(spec.await_count, 0) self.assertIsNone(spec.await_args) self.assertEqual(spec.await_args_list, []) spec.assert_not_awaited() run(main()) self.assertTrue(iscoroutinefunction(spec)) self.assertTrue(asyncio.iscoroutine(awaitable)) self.assertEqual(spec.await_count, 1) self.assertEqual(spec.await_args, call(1, 2, c=3)) self.assertEqual(spec.await_args_list, [call(1, 2, c=3)]) spec.assert_awaited_once() spec.assert_awaited_once_with(1, 2, c=3) spec.assert_awaited_with(1, 2, c=3) spec.assert_awaited() with self.assertRaises(AssertionError): spec.assert_any_await(e=1) def test_patch_with_autospec(self): async def test_async(): with patch(f"{__name__}.async_func_args", autospec=True) as mock_method: awaitable = mock_method(1, 2, c=3) self.assertIsInstance(mock_method.mock, AsyncMock) self.assertTrue(iscoroutinefunction(mock_method)) self.assertTrue(asyncio.iscoroutine(awaitable)) self.assertTrue(inspect.isawaitable(awaitable)) # Verify the default values during mock setup self.assertEqual(mock_method.await_count, 0) self.assertEqual(mock_method.await_args_list, []) self.assertIsNone(mock_method.await_args) mock_method.assert_not_awaited() await awaitable self.assertEqual(mock_method.await_count, 1) self.assertEqual(mock_method.await_args, call(1, 2, c=3)) self.assertEqual(mock_method.await_args_list, [call(1, 2, c=3)]) mock_method.assert_awaited_once() mock_method.assert_awaited_once_with(1, 2, c=3) mock_method.assert_awaited_with(1, 2, c=3) mock_method.assert_awaited() mock_method.reset_mock() self.assertEqual(mock_method.await_count, 0) self.assertIsNone(mock_method.await_args) self.assertEqual(mock_method.await_args_list, []) run(test_async()) class AsyncSpecTest(unittest.TestCase): def test_spec_normal_methods_on_class(self): def inner_test(mock_type): mock = mock_type(AsyncClass) self.assertIsInstance(mock.async_method, AsyncMock) self.assertIsInstance(mock.normal_method, MagicMock) for mock_type in [AsyncMock, MagicMock]: with self.subTest(f"test method types with {mock_type}"): inner_test(mock_type) def test_spec_normal_methods_on_class_with_mock(self): mock = Mock(AsyncClass) self.assertIsInstance(mock.async_method, AsyncMock) self.assertIsInstance(mock.normal_method, Mock) def test_spec_mock_type_kw(self): def inner_test(mock_type): async_mock = mock_type(spec=async_func) self.assertIsInstance(async_mock, mock_type) with assertNeverAwaited(self): self.assertTrue(inspect.isawaitable(async_mock())) sync_mock = mock_type(spec=normal_func) self.assertIsInstance(sync_mock, mock_type) for mock_type in [AsyncMock, MagicMock, Mock]: with self.subTest(f"test spec kwarg with {mock_type}"): inner_test(mock_type) def test_spec_mock_type_positional(self): def inner_test(mock_type): async_mock = mock_type(async_func) self.assertIsInstance(async_mock, mock_type) with assertNeverAwaited(self): self.assertTrue(inspect.isawaitable(async_mock())) sync_mock = mock_type(normal_func) self.assertIsInstance(sync_mock, mock_type) for mock_type in [AsyncMock, MagicMock, Mock]: with self.subTest(f"test spec positional with {mock_type}"): inner_test(mock_type) def test_spec_as_normal_kw_AsyncMock(self): mock = AsyncMock(spec=normal_func) self.assertIsInstance(mock, AsyncMock) m = mock() self.assertTrue(inspect.isawaitable(m)) run(m) def test_spec_as_normal_positional_AsyncMock(self): mock = AsyncMock(normal_func) self.assertIsInstance(mock, AsyncMock) m = mock() self.assertTrue(inspect.isawaitable(m)) run(m) def test_spec_async_mock(self): @patch.object(AsyncClass, 'async_method', spec=True) def test_async(mock_method): self.assertIsInstance(mock_method, AsyncMock) test_async() def test_spec_parent_not_async_attribute_is(self): @patch(async_foo_name, spec=True) def test_async(mock_method): self.assertIsInstance(mock_method, MagicMock) self.assertIsInstance(mock_method.async_method, AsyncMock) test_async() def test_target_async_spec_not(self): @patch.object(AsyncClass, 'async_method', spec=NormalClass.a) def test_async_attribute(mock_method): self.assertIsInstance(mock_method, MagicMock) self.assertFalse(inspect.iscoroutine(mock_method)) self.assertFalse(inspect.isawaitable(mock_method)) test_async_attribute() def test_target_not_async_spec_is(self): @patch.object(NormalClass, 'a', spec=async_func) def test_attribute_not_async_spec_is(mock_async_func): self.assertIsInstance(mock_async_func, AsyncMock) test_attribute_not_async_spec_is() def test_spec_async_attributes(self): @patch(normal_foo_name, spec=AsyncClass) def test_async_attributes_coroutines(MockNormalClass): self.assertIsInstance(MockNormalClass.async_method, AsyncMock) self.assertIsInstance(MockNormalClass, MagicMock) test_async_attributes_coroutines() class AsyncSpecSetTest(unittest.TestCase): def test_is_AsyncMock_patch(self): @patch.object(AsyncClass, 'async_method', spec_set=True) def test_async(async_method): self.assertIsInstance(async_method, AsyncMock) test_async() def test_is_async_AsyncMock(self): mock = AsyncMock(spec_set=AsyncClass.async_method) self.assertTrue(iscoroutinefunction(mock)) self.assertIsInstance(mock, AsyncMock) def test_is_child_AsyncMock(self): mock = MagicMock(spec_set=AsyncClass) self.assertTrue(iscoroutinefunction(mock.async_method)) self.assertFalse(iscoroutinefunction(mock.normal_method)) self.assertIsInstance(mock.async_method, AsyncMock) self.assertIsInstance(mock.normal_method, MagicMock) self.assertIsInstance(mock, MagicMock) def test_magicmock_lambda_spec(self): mock_obj = MagicMock() mock_obj.mock_func = MagicMock(spec=lambda x: x) with patch.object(mock_obj, "mock_func") as cm: self.assertIsInstance(cm, MagicMock) class AsyncArguments(IsolatedAsyncioTestCase): async def test_add_return_value(self): async def addition(self, var): pass mock = AsyncMock(addition, return_value=10) output = await mock(5) self.assertEqual(output, 10) async def test_add_side_effect_exception(self): async def addition(var): pass mock = AsyncMock(addition, side_effect=Exception('err')) with self.assertRaises(Exception): await mock(5) async def test_add_side_effect_coroutine(self): async def addition(var): return var + 1 mock = AsyncMock(side_effect=addition) result = await mock(5) self.assertEqual(result, 6) async def test_add_side_effect_normal_function(self): def addition(var): return var + 1 mock = AsyncMock(side_effect=addition) result = await mock(5) self.assertEqual(result, 6) async def test_add_side_effect_iterable(self): vals = [1, 2, 3] mock = AsyncMock(side_effect=vals) for item in vals: self.assertEqual(await mock(), item) with self.assertRaises(StopAsyncIteration) as e: await mock() async def test_add_side_effect_exception_iterable(self): class SampleException(Exception): pass vals = [1, SampleException("foo")] mock = AsyncMock(side_effect=vals) self.assertEqual(await mock(), 1) with self.assertRaises(SampleException) as e: await mock() async def test_return_value_AsyncMock(self): value = AsyncMock(return_value=10) mock = AsyncMock(return_value=value) result = await mock() self.assertIs(result, value) async def test_return_value_awaitable(self): fut = asyncio.Future() fut.set_result(None) mock = AsyncMock(return_value=fut) result = await mock() self.assertIsInstance(result, asyncio.Future) async def test_side_effect_awaitable_values(self): fut = asyncio.Future() fut.set_result(None) mock = AsyncMock(side_effect=[fut]) result = await mock() self.assertIsInstance(result, asyncio.Future) with self.assertRaises(StopAsyncIteration): await mock() async def test_side_effect_is_AsyncMock(self): effect = AsyncMock(return_value=10) mock = AsyncMock(side_effect=effect) result = await mock() self.assertEqual(result, 10) async def test_wraps_coroutine(self): value = asyncio.Future() ran = False async def inner(): nonlocal ran ran = True return value mock = AsyncMock(wraps=inner) result = await mock() self.assertEqual(result, value) mock.assert_awaited() self.assertTrue(ran) async def test_wraps_normal_function(self): value = 1 ran = False def inner(): nonlocal ran ran = True return value mock = AsyncMock(wraps=inner) result = await mock() self.assertEqual(result, value) mock.assert_awaited() self.assertTrue(ran) async def test_await_args_list_order(self): async_mock = AsyncMock() mock2 = async_mock(2) mock1 = async_mock(1) await mock1 await mock2 async_mock.assert_has_awaits([call(1), call(2)]) self.assertEqual(async_mock.await_args_list, [call(1), call(2)]) self.assertEqual(async_mock.call_args_list, [call(2), call(1)]) class AsyncMagicMethods(unittest.TestCase): def test_async_magic_methods_return_async_mocks(self): m_mock = MagicMock() self.assertIsInstance(m_mock.__aenter__, AsyncMock) self.assertIsInstance(m_mock.__aexit__, AsyncMock) self.assertIsInstance(m_mock.__anext__, AsyncMock) # __aiter__ is actually a synchronous object # so should return a MagicMock self.assertIsInstance(m_mock.__aiter__, MagicMock) def test_sync_magic_methods_return_magic_mocks(self): a_mock = AsyncMock() self.assertIsInstance(a_mock.__enter__, MagicMock) self.assertIsInstance(a_mock.__exit__, MagicMock) self.assertIsInstance(a_mock.__next__, MagicMock) self.assertIsInstance(a_mock.__len__, MagicMock) def test_magicmock_has_async_magic_methods(self): m_mock = MagicMock() self.assertTrue(hasattr(m_mock, "__aenter__")) self.assertTrue(hasattr(m_mock, "__aexit__")) self.assertTrue(hasattr(m_mock, "__anext__")) def test_asyncmock_has_sync_magic_methods(self): a_mock = AsyncMock() self.assertTrue(hasattr(a_mock, "__enter__")) self.assertTrue(hasattr(a_mock, "__exit__")) self.assertTrue(hasattr(a_mock, "__next__")) self.assertTrue(hasattr(a_mock, "__len__")) def test_magic_methods_are_async_functions(self): m_mock = MagicMock() self.assertIsInstance(m_mock.__aenter__, AsyncMock) self.assertIsInstance(m_mock.__aexit__, AsyncMock) # AsyncMocks are also coroutine functions self.assertTrue(iscoroutinefunction(m_mock.__aenter__)) self.assertTrue(iscoroutinefunction(m_mock.__aexit__)) class AsyncContextManagerTest(unittest.TestCase): class WithAsyncContextManager: async def __aenter__(self, *args, **kwargs): pass async def __aexit__(self, *args, **kwargs): pass class WithSyncContextManager: def __enter__(self, *args, **kwargs): pass def __exit__(self, *args, **kwargs): pass class ProductionCode: # Example real-world(ish) code def __init__(self): self.session = None async def main(self): async with self.session.post('https://python.org') as response: val = await response.json() return val def test_set_return_value_of_aenter(self): def inner_test(mock_type): pc = self.ProductionCode() pc.session = MagicMock(name='sessionmock') cm = mock_type(name='magic_cm') response = AsyncMock(name='response') response.json = AsyncMock(return_value={'json': 123}) cm.__aenter__.return_value = response pc.session.post.return_value = cm result = run(pc.main()) self.assertEqual(result, {'json': 123}) for mock_type in [AsyncMock, MagicMock]: with self.subTest(f"test set return value of aenter with {mock_type}"): inner_test(mock_type) def test_mock_supports_async_context_manager(self): def inner_test(mock_type): called = False cm = self.WithAsyncContextManager() cm_mock = mock_type(cm) async def use_context_manager(): nonlocal called async with cm_mock as result: called = True return result cm_result = run(use_context_manager()) self.assertTrue(called) self.assertTrue(cm_mock.__aenter__.called) self.assertTrue(cm_mock.__aexit__.called) cm_mock.__aenter__.assert_awaited() cm_mock.__aexit__.assert_awaited() # We mock __aenter__ so it does not return self self.assertIsNot(cm_mock, cm_result) for mock_type in [AsyncMock, MagicMock]: with self.subTest(f"test context manager magics with {mock_type}"): inner_test(mock_type) def test_mock_customize_async_context_manager(self): instance = self.WithAsyncContextManager() mock_instance = MagicMock(instance) expected_result = object() mock_instance.__aenter__.return_value = expected_result async def use_context_manager(): async with mock_instance as result: return result self.assertIs(run(use_context_manager()), expected_result) def test_mock_customize_async_context_manager_with_coroutine(self): enter_called = False exit_called = False async def enter_coroutine(*args): nonlocal enter_called enter_called = True async def exit_coroutine(*args): nonlocal exit_called exit_called = True instance = self.WithAsyncContextManager() mock_instance = MagicMock(instance) mock_instance.__aenter__ = enter_coroutine mock_instance.__aexit__ = exit_coroutine async def use_context_manager(): async with mock_instance: pass run(use_context_manager()) self.assertTrue(enter_called) self.assertTrue(exit_called) def test_context_manager_raise_exception_by_default(self): async def raise_in(context_manager): async with context_manager: raise TypeError() instance = self.WithAsyncContextManager() mock_instance = MagicMock(instance) with self.assertRaises(TypeError): run(raise_in(mock_instance)) class AsyncIteratorTest(unittest.TestCase): class WithAsyncIterator(object): def __init__(self): self.items = ["foo", "NormalFoo", "baz"] def __aiter__(self): pass async def __anext__(self): pass def test_aiter_set_return_value(self): mock_iter = AsyncMock(name="tester") mock_iter.__aiter__.return_value = [1, 2, 3] async def main(): return [i async for i in mock_iter] result = run(main()) self.assertEqual(result, [1, 2, 3]) def test_mock_aiter_and_anext_asyncmock(self): def inner_test(mock_type): instance = self.WithAsyncIterator() mock_instance = mock_type(instance) # Check that the mock and the real thing bahave the same # __aiter__ is not actually async, so not a coroutinefunction self.assertFalse(iscoroutinefunction(instance.__aiter__)) self.assertFalse(iscoroutinefunction(mock_instance.__aiter__)) # __anext__ is async self.assertTrue(iscoroutinefunction(instance.__anext__)) self.assertTrue(iscoroutinefunction(mock_instance.__anext__)) for mock_type in [AsyncMock, MagicMock]: with self.subTest(f"test aiter and anext corourtine with {mock_type}"): inner_test(mock_type) def test_mock_async_for(self): async def iterate(iterator): accumulator = [] async for item in iterator: accumulator.append(item) return accumulator expected = ["FOO", "BAR", "BAZ"] def test_default(mock_type): mock_instance = mock_type(self.WithAsyncIterator()) self.assertEqual(run(iterate(mock_instance)), []) def test_set_return_value(mock_type): mock_instance = mock_type(self.WithAsyncIterator()) mock_instance.__aiter__.return_value = expected[:] self.assertEqual(run(iterate(mock_instance)), expected) def test_set_return_value_iter(mock_type): mock_instance = mock_type(self.WithAsyncIterator()) mock_instance.__aiter__.return_value = iter(expected[:]) self.assertEqual(run(iterate(mock_instance)), expected) for mock_type in [AsyncMock, MagicMock]: with self.subTest(f"default value with {mock_type}"): test_default(mock_type) with self.subTest(f"set return_value with {mock_type}"): test_set_return_value(mock_type) with self.subTest(f"set return_value iterator with {mock_type}"): test_set_return_value_iter(mock_type) class AsyncMockAssert(unittest.TestCase): def setUp(self): self.mock = AsyncMock() async def _runnable_test(self, *args, **kwargs): await self.mock(*args, **kwargs) async def _await_coroutine(self, coroutine): return await coroutine def test_assert_called_but_not_awaited(self): mock = AsyncMock(AsyncClass) with assertNeverAwaited(self): mock.async_method() self.assertTrue(iscoroutinefunction(mock.async_method)) mock.async_method.assert_called() mock.async_method.assert_called_once() mock.async_method.assert_called_once_with() with self.assertRaises(AssertionError): mock.assert_awaited() with self.assertRaises(AssertionError): mock.async_method.assert_awaited() def test_assert_called_then_awaited(self): mock = AsyncMock(AsyncClass) mock_coroutine = mock.async_method() mock.async_method.assert_called() mock.async_method.assert_called_once() mock.async_method.assert_called_once_with() with self.assertRaises(AssertionError): mock.async_method.assert_awaited() run(self._await_coroutine(mock_coroutine)) # Assert we haven't re-called the function mock.async_method.assert_called_once() mock.async_method.assert_awaited() mock.async_method.assert_awaited_once() mock.async_method.assert_awaited_once_with() def test_assert_called_and_awaited_at_same_time(self): with self.assertRaises(AssertionError): self.mock.assert_awaited() with self.assertRaises(AssertionError): self.mock.assert_called() run(self._runnable_test()) self.mock.assert_called_once() self.mock.assert_awaited_once() def test_assert_called_twice_and_awaited_once(self): mock = AsyncMock(AsyncClass) coroutine = mock.async_method() # The first call will be awaited so no warning there # But this call will never get awaited, so it will warn here with assertNeverAwaited(self): mock.async_method() with self.assertRaises(AssertionError): mock.async_method.assert_awaited() mock.async_method.assert_called() run(self._await_coroutine(coroutine)) mock.async_method.assert_awaited() mock.async_method.assert_awaited_once() def test_assert_called_once_and_awaited_twice(self): mock = AsyncMock(AsyncClass) coroutine = mock.async_method() mock.async_method.assert_called_once() run(self._await_coroutine(coroutine)) with self.assertRaises(RuntimeError): # Cannot reuse already awaited coroutine run(self._await_coroutine(coroutine)) mock.async_method.assert_awaited() def test_assert_awaited_but_not_called(self): with self.assertRaises(AssertionError): self.mock.assert_awaited() with self.assertRaises(AssertionError): self.mock.assert_called() with self.assertRaises(TypeError): # You cannot await an AsyncMock, it must be a coroutine run(self._await_coroutine(self.mock)) with self.assertRaises(AssertionError): self.mock.assert_awaited() with self.assertRaises(AssertionError): self.mock.assert_called() def test_assert_has_calls_not_awaits(self): kalls = [call('foo')] with assertNeverAwaited(self): self.mock('foo') self.mock.assert_has_calls(kalls) with self.assertRaises(AssertionError): self.mock.assert_has_awaits(kalls) def test_assert_has_mock_calls_on_async_mock_no_spec(self): with assertNeverAwaited(self): self.mock() kalls_empty = [('', (), {})] self.assertEqual(self.mock.mock_calls, kalls_empty) with assertNeverAwaited(self): self.mock('foo') with assertNeverAwaited(self): self.mock('baz') mock_kalls = ([call(), call('foo'), call('baz')]) self.assertEqual(self.mock.mock_calls, mock_kalls) def test_assert_has_mock_calls_on_async_mock_with_spec(self): a_class_mock = AsyncMock(AsyncClass) with assertNeverAwaited(self): a_class_mock.async_method() kalls_empty = [('', (), {})] self.assertEqual(a_class_mock.async_method.mock_calls, kalls_empty) self.assertEqual(a_class_mock.mock_calls, [call.async_method()]) with assertNeverAwaited(self): a_class_mock.async_method(1, 2, 3, a=4, b=5) method_kalls = [call(), call(1, 2, 3, a=4, b=5)] mock_kalls = [call.async_method(), call.async_method(1, 2, 3, a=4, b=5)] self.assertEqual(a_class_mock.async_method.mock_calls, method_kalls) self.assertEqual(a_class_mock.mock_calls, mock_kalls) def test_async_method_calls_recorded(self): with assertNeverAwaited(self): self.mock.something(3, fish=None) with assertNeverAwaited(self): self.mock.something_else.something(6, cake=sentinel.Cake) self.assertEqual(self.mock.method_calls, [ ("something", (3,), {'fish': None}), ("something_else.something", (6,), {'cake': sentinel.Cake}) ], "method calls not recorded correctly") self.assertEqual(self.mock.something_else.method_calls, [("something", (6,), {'cake': sentinel.Cake})], "method calls not recorded correctly") def test_async_arg_lists(self): def assert_attrs(mock): names = ('call_args_list', 'method_calls', 'mock_calls') for name in names: attr = getattr(mock, name) self.assertIsInstance(attr, _CallList) self.assertIsInstance(attr, list) self.assertEqual(attr, []) assert_attrs(self.mock) with assertNeverAwaited(self): self.mock() with assertNeverAwaited(self): self.mock(1, 2) with assertNeverAwaited(self): self.mock(a=3) self.mock.reset_mock() assert_attrs(self.mock) a_mock = AsyncMock(AsyncClass) with assertNeverAwaited(self): a_mock.async_method() with assertNeverAwaited(self): a_mock.async_method(1, a=3) a_mock.reset_mock() assert_attrs(a_mock) def test_assert_awaited(self): with self.assertRaises(AssertionError): self.mock.assert_awaited() run(self._runnable_test()) self.mock.assert_awaited() def test_assert_awaited_once(self): with self.assertRaises(AssertionError): self.mock.assert_awaited_once() run(self._runnable_test()) self.mock.assert_awaited_once() run(self._runnable_test()) with self.assertRaises(AssertionError): self.mock.assert_awaited_once() def test_assert_awaited_with(self): msg = 'Not awaited' with self.assertRaisesRegex(AssertionError, msg): self.mock.assert_awaited_with('foo') run(self._runnable_test()) msg = 'expected await not found' with self.assertRaisesRegex(AssertionError, msg): self.mock.assert_awaited_with('foo') run(self._runnable_test('foo')) self.mock.assert_awaited_with('foo') run(self._runnable_test('SomethingElse')) with self.assertRaises(AssertionError): self.mock.assert_awaited_with('foo') def test_assert_awaited_once_with(self): with self.assertRaises(AssertionError): self.mock.assert_awaited_once_with('foo') run(self._runnable_test('foo')) self.mock.assert_awaited_once_with('foo') run(self._runnable_test('foo')) with self.assertRaises(AssertionError): self.mock.assert_awaited_once_with('foo') def test_assert_any_wait(self): with self.assertRaises(AssertionError): self.mock.assert_any_await('foo') run(self._runnable_test('baz')) with self.assertRaises(AssertionError): self.mock.assert_any_await('foo') run(self._runnable_test('foo')) self.mock.assert_any_await('foo') run(self._runnable_test('SomethingElse')) self.mock.assert_any_await('foo') def test_assert_has_awaits_no_order(self): calls = [call('foo'), call('baz')] with self.assertRaises(AssertionError) as cm: self.mock.assert_has_awaits(calls) self.assertEqual(len(cm.exception.args), 1) run(self._runnable_test('foo')) with self.assertRaises(AssertionError): self.mock.assert_has_awaits(calls) run(self._runnable_test('foo')) with self.assertRaises(AssertionError): self.mock.assert_has_awaits(calls) run(self._runnable_test('baz')) self.mock.assert_has_awaits(calls) run(self._runnable_test('SomethingElse')) self.mock.assert_has_awaits(calls) def test_awaits_asserts_with_any(self): class Foo: def __eq__(self, other): pass run(self._runnable_test(Foo(), 1)) self.mock.assert_has_awaits([call(ANY, 1)]) self.mock.assert_awaited_with(ANY, 1) self.mock.assert_any_await(ANY, 1) def test_awaits_asserts_with_spec_and_any(self): class Foo: def __eq__(self, other): pass mock_with_spec = AsyncMock(spec=Foo) async def _custom_mock_runnable_test(*args): await mock_with_spec(*args) run(_custom_mock_runnable_test(Foo(), 1)) mock_with_spec.assert_has_awaits([call(ANY, 1)]) mock_with_spec.assert_awaited_with(ANY, 1) mock_with_spec.assert_any_await(ANY, 1) def test_assert_has_awaits_ordered(self): calls = [call('foo'), call('baz')] with self.assertRaises(AssertionError): self.mock.assert_has_awaits(calls, any_order=True) run(self._runnable_test('baz')) with self.assertRaises(AssertionError): self.mock.assert_has_awaits(calls, any_order=True) run(self._runnable_test('bamf')) with self.assertRaises(AssertionError): self.mock.assert_has_awaits(calls, any_order=True) run(self._runnable_test('foo')) self.mock.assert_has_awaits(calls, any_order=True) run(self._runnable_test('qux')) self.mock.assert_has_awaits(calls, any_order=True) def test_assert_not_awaited(self): self.mock.assert_not_awaited() run(self._runnable_test()) with self.assertRaises(AssertionError): self.mock.assert_not_awaited() def test_assert_has_awaits_not_matching_spec_error(self): async def f(x=None): pass self.mock = AsyncMock(spec=f) run(self._runnable_test(1)) with self.assertRaisesRegex( AssertionError, '^{}$'.format( re.escape('Awaits not found.\n' 'Expected: [call()]\n' 'Actual: [call(1)]'))) as cm: self.mock.assert_has_awaits([call()]) self.assertIsNone(cm.exception.__cause__) with self.assertRaisesRegex( AssertionError, '^{}$'.format( re.escape( 'Error processing expected awaits.\n' "Errors: [None, TypeError('too many positional " "arguments')]\n" 'Expected: [call(), call(1, 2)]\n' 'Actual: [call(1)]').replace( "arguments\\'", "arguments\\',?") )) as cm: self.mock.assert_has_awaits([call(), call(1, 2)]) self.assertIsInstance(cm.exception.__cause__, TypeError) mock-4.0.3/mock/tests/testcallable.py000066400000000000000000000102471376434722300175720ustar00rootroot00000000000000# Copyright (C) 2007-2012 Michael Foord & the mock team # E-mail: fuzzyman AT voidspace DOT org DOT uk # http://www.voidspace.org.uk/python/mock/ import unittest from mock.tests.support import is_instance, X, SomeClass from mock import ( Mock, MagicMock, NonCallableMagicMock, NonCallableMock, patch, create_autospec, ) from mock.mock import CallableMixin class TestCallable(unittest.TestCase): def assertNotCallable(self, mock): self.assertTrue(is_instance(mock, NonCallableMagicMock)) self.assertFalse(is_instance(mock, CallableMixin)) def test_non_callable(self): for mock in NonCallableMagicMock(), NonCallableMock(): self.assertRaises(TypeError, mock) self.assertFalse(hasattr(mock, '__call__')) self.assertIn(mock.__class__.__name__, repr(mock)) def test_hierarchy(self): self.assertTrue(issubclass(MagicMock, Mock)) self.assertTrue(issubclass(NonCallableMagicMock, NonCallableMock)) def test_attributes(self): one = NonCallableMock() self.assertTrue(issubclass(type(one.one), Mock)) two = NonCallableMagicMock() self.assertTrue(issubclass(type(two.two), MagicMock)) def test_subclasses(self): class MockSub(Mock): pass one = MockSub() self.assertTrue(issubclass(type(one.one), MockSub)) class MagicSub(MagicMock): pass two = MagicSub() self.assertTrue(issubclass(type(two.two), MagicSub)) def test_patch_spec(self): patcher = patch('%s.X' % __name__, spec=True) mock = patcher.start() self.addCleanup(patcher.stop) instance = mock() mock.assert_called_once_with() self.assertNotCallable(instance) self.assertRaises(TypeError, instance) def test_patch_spec_set(self): patcher = patch('%s.X' % __name__, spec_set=True) mock = patcher.start() self.addCleanup(patcher.stop) instance = mock() mock.assert_called_once_with() self.assertNotCallable(instance) self.assertRaises(TypeError, instance) def test_patch_spec_instance(self): patcher = patch('%s.X' % __name__, spec=X()) mock = patcher.start() self.addCleanup(patcher.stop) self.assertNotCallable(mock) self.assertRaises(TypeError, mock) def test_patch_spec_set_instance(self): patcher = patch('%s.X' % __name__, spec_set=X()) mock = patcher.start() self.addCleanup(patcher.stop) self.assertNotCallable(mock) self.assertRaises(TypeError, mock) def test_patch_spec_callable_class(self): class CallableX(X): def __call__(self): pass class Sub(CallableX): pass class Multi(SomeClass, Sub): pass for arg in 'spec', 'spec_set': for Klass in CallableX, Sub, Multi: with patch('%s.X' % __name__, **{arg: Klass}) as mock: instance = mock() mock.assert_called_once_with() self.assertTrue(is_instance(instance, MagicMock)) # inherited spec self.assertRaises(AttributeError, getattr, instance, 'foobarbaz') result = instance() # instance is callable, result has no spec instance.assert_called_once_with() result(3, 2, 1) result.assert_called_once_with(3, 2, 1) result.foo(3, 2, 1) result.foo.assert_called_once_with(3, 2, 1) def test_create_autospec(self): mock = create_autospec(X) instance = mock() self.assertRaises(TypeError, instance) mock = create_autospec(X()) self.assertRaises(TypeError, mock) def test_create_autospec_instance(self): mock = create_autospec(SomeClass, instance=True) self.assertRaises(TypeError, mock) mock.wibble() mock.wibble.assert_called_once_with() self.assertRaises(TypeError, mock.wibble, 'some', 'args') if __name__ == "__main__": unittest.main() mock-4.0.3/mock/tests/testhelpers.py000066400000000000000000001021011376434722300174640ustar00rootroot00000000000000import inspect import time import types import unittest from mock import ( call, create_autospec, MagicMock, Mock, ANY, patch, PropertyMock ) from mock.mock import _Call, _CallList, _callable from mock import IS_PYPY from datetime import datetime from functools import partial import pytest class SomeClass(object): def one(self, a, b): pass def two(self): pass def three(self, a=None): pass class AnyTest(unittest.TestCase): def test_any(self): self.assertEqual(ANY, object()) mock = Mock() mock(ANY) mock.assert_called_with(ANY) mock = Mock() mock(foo=ANY) mock.assert_called_with(foo=ANY) def test_repr(self): self.assertEqual(repr(ANY), '') self.assertEqual(str(ANY), '') def test_any_and_datetime(self): mock = Mock() mock(datetime.now(), foo=datetime.now()) mock.assert_called_with(ANY, foo=ANY) def test_any_mock_calls_comparison_order(self): mock = Mock() class Foo(object): def __eq__(self, other): pass def __ne__(self, other): pass for d in datetime.now(), Foo(): mock.reset_mock() mock(d, foo=d, bar=d) mock.method(d, zinga=d, alpha=d) mock().method(a1=d, z99=d) expected = [ call(ANY, foo=ANY, bar=ANY), call.method(ANY, zinga=ANY, alpha=ANY), call(), call().method(a1=ANY, z99=ANY) ] self.assertEqual(expected, mock.mock_calls) self.assertEqual(mock.mock_calls, expected) def test_any_no_spec(self): # This is a regression test for bpo-37555 class Foo: def __eq__(self, other): pass mock = Mock() mock(Foo(), 1) mock.assert_has_calls([call(ANY, 1)]) mock.assert_called_with(ANY, 1) mock.assert_any_call(ANY, 1) def test_any_and_spec_set(self): # This is a regression test for bpo-37555 class Foo: def __eq__(self, other): pass mock = Mock(spec=Foo) mock(Foo(), 1) mock.assert_has_calls([call(ANY, 1)]) mock.assert_called_with(ANY, 1) mock.assert_any_call(ANY, 1) class CallTest(unittest.TestCase): def test_call_with_call(self): kall = _Call() self.assertEqual(kall, _Call()) self.assertEqual(kall, _Call(('',))) self.assertEqual(kall, _Call(((),))) self.assertEqual(kall, _Call(({},))) self.assertEqual(kall, _Call(('', ()))) self.assertEqual(kall, _Call(('', {}))) self.assertEqual(kall, _Call(('', (), {}))) self.assertEqual(kall, _Call(('foo',))) self.assertEqual(kall, _Call(('bar', ()))) self.assertEqual(kall, _Call(('baz', {}))) self.assertEqual(kall, _Call(('spam', (), {}))) kall = _Call(((1, 2, 3),)) self.assertEqual(kall, _Call(((1, 2, 3),))) self.assertEqual(kall, _Call(('', (1, 2, 3)))) self.assertEqual(kall, _Call(((1, 2, 3), {}))) self.assertEqual(kall, _Call(('', (1, 2, 3), {}))) kall = _Call(((1, 2, 4),)) self.assertNotEqual(kall, _Call(('', (1, 2, 3)))) self.assertNotEqual(kall, _Call(('', (1, 2, 3), {}))) kall = _Call(('foo', (1, 2, 4),)) self.assertNotEqual(kall, _Call(('', (1, 2, 4)))) self.assertNotEqual(kall, _Call(('', (1, 2, 4), {}))) self.assertNotEqual(kall, _Call(('bar', (1, 2, 4)))) self.assertNotEqual(kall, _Call(('bar', (1, 2, 4), {}))) kall = _Call(({'a': 3},)) self.assertEqual(kall, _Call(('', (), {'a': 3}))) self.assertEqual(kall, _Call(('', {'a': 3}))) self.assertEqual(kall, _Call(((), {'a': 3}))) self.assertEqual(kall, _Call(({'a': 3},))) def test_empty__Call(self): args = _Call() self.assertEqual(args, ()) self.assertEqual(args, ('foo',)) self.assertEqual(args, ((),)) self.assertEqual(args, ('foo', ())) self.assertEqual(args, ('foo',(), {})) self.assertEqual(args, ('foo', {})) self.assertEqual(args, ({},)) def test_named_empty_call(self): args = _Call(('foo', (), {})) self.assertEqual(args, ('foo',)) self.assertEqual(args, ('foo', ())) self.assertEqual(args, ('foo',(), {})) self.assertEqual(args, ('foo', {})) self.assertNotEqual(args, ((),)) self.assertNotEqual(args, ()) self.assertNotEqual(args, ({},)) self.assertNotEqual(args, ('bar',)) self.assertNotEqual(args, ('bar', ())) self.assertNotEqual(args, ('bar', {})) def test_call_with_args(self): args = _Call(((1, 2, 3), {})) self.assertEqual(args, ((1, 2, 3),)) self.assertEqual(args, ('foo', (1, 2, 3))) self.assertEqual(args, ('foo', (1, 2, 3), {})) self.assertEqual(args, ((1, 2, 3), {})) self.assertEqual(args.args, (1, 2, 3)) self.assertEqual(args.kwargs, {}) def test_named_call_with_args(self): args = _Call(('foo', (1, 2, 3), {})) self.assertEqual(args, ('foo', (1, 2, 3))) self.assertEqual(args, ('foo', (1, 2, 3), {})) self.assertEqual(args.args, (1, 2, 3)) self.assertEqual(args.kwargs, {}) self.assertNotEqual(args, ((1, 2, 3),)) self.assertNotEqual(args, ((1, 2, 3), {})) def test_call_with_kwargs(self): args = _Call(((), dict(a=3, b=4))) self.assertEqual(args, (dict(a=3, b=4),)) self.assertEqual(args, ('foo', dict(a=3, b=4))) self.assertEqual(args, ('foo', (), dict(a=3, b=4))) self.assertEqual(args, ((), dict(a=3, b=4))) self.assertEqual(args.args, ()) self.assertEqual(args.kwargs, dict(a=3, b=4)) def test_named_call_with_kwargs(self): args = _Call(('foo', (), dict(a=3, b=4))) self.assertEqual(args, ('foo', dict(a=3, b=4))) self.assertEqual(args, ('foo', (), dict(a=3, b=4))) self.assertEqual(args.args, ()) self.assertEqual(args.kwargs, dict(a=3, b=4)) self.assertNotEqual(args, (dict(a=3, b=4),)) self.assertNotEqual(args, ((), dict(a=3, b=4))) def test_call_with_args_call_empty_name(self): args = _Call(((1, 2, 3), {})) self.assertEqual(args, call(1, 2, 3)) self.assertEqual(call(1, 2, 3), args) self.assertIn(call(1, 2, 3), [args]) def test_call_ne(self): self.assertNotEqual(_Call(((1, 2, 3),)), call(1, 2)) self.assertFalse(_Call(((1, 2, 3),)) != call(1, 2, 3)) self.assertTrue(_Call(((1, 2), {})) != call(1, 2, 3)) def test_call_non_tuples(self): kall = _Call(((1, 2, 3),)) for value in 1, None, self, int: self.assertNotEqual(kall, value) self.assertFalse(kall == value) def test_repr(self): self.assertEqual(repr(_Call()), 'call()') self.assertEqual(repr(_Call(('foo',))), 'call.foo()') self.assertEqual(repr(_Call(((1, 2, 3), {'a': 'b'}))), "call(1, 2, 3, a='b')") self.assertEqual(repr(_Call(('bar', (1, 2, 3), {'a': 'b'}))), "call.bar(1, 2, 3, a='b')") self.assertEqual(repr(call), 'call') self.assertEqual(str(call), 'call') self.assertEqual(repr(call()), 'call()') self.assertEqual(repr(call(1)), 'call(1)') self.assertEqual(repr(call(zz='thing')), "call(zz='thing')") self.assertEqual(repr(call().foo), 'call().foo') self.assertEqual(repr(call(1).foo.bar(a=3).bing), 'call().foo.bar().bing') self.assertEqual( repr(call().foo(1, 2, a=3)), "call().foo(1, 2, a=3)" ) self.assertEqual(repr(call()()), "call()()") self.assertEqual(repr(call(1)(2)), "call()(2)") self.assertEqual( repr(call()().bar().baz.beep(1)), "call()().bar().baz.beep(1)" ) def test_call(self): self.assertEqual(call(), ('', (), {})) self.assertEqual(call('foo', 'bar', one=3, two=4), ('', ('foo', 'bar'), {'one': 3, 'two': 4})) mock = Mock() mock(1, 2, 3) mock(a=3, b=6) self.assertEqual(mock.call_args_list, [call(1, 2, 3), call(a=3, b=6)]) def test_attribute_call(self): self.assertEqual(call.foo(1), ('foo', (1,), {})) self.assertEqual(call.bar.baz(fish='eggs'), ('bar.baz', (), {'fish': 'eggs'})) mock = Mock() mock.foo(1, 2 ,3) mock.bar.baz(a=3, b=6) self.assertEqual(mock.method_calls, [call.foo(1, 2, 3), call.bar.baz(a=3, b=6)]) def test_extended_call(self): result = call(1).foo(2).bar(3, a=4) self.assertEqual(result, ('().foo().bar', (3,), dict(a=4))) mock = MagicMock() mock(1, 2, a=3, b=4) self.assertEqual(mock.call_args, call(1, 2, a=3, b=4)) self.assertNotEqual(mock.call_args, call(1, 2, 3)) self.assertEqual(mock.call_args_list, [call(1, 2, a=3, b=4)]) self.assertEqual(mock.mock_calls, [call(1, 2, a=3, b=4)]) mock = MagicMock() mock.foo(1).bar()().baz.beep(a=6) last_call = call.foo(1).bar()().baz.beep(a=6) self.assertEqual(mock.mock_calls[-1], last_call) self.assertEqual(mock.mock_calls, last_call.call_list()) def test_extended_not_equal(self): a = call(x=1).foo b = call(x=2).foo self.assertEqual(a, a) self.assertEqual(b, b) self.assertNotEqual(a, b) def test_nested_calls_not_equal(self): a = call(x=1).foo().bar b = call(x=2).foo().bar self.assertEqual(a, a) self.assertEqual(b, b) self.assertNotEqual(a, b) def test_call_list(self): mock = MagicMock() mock(1) self.assertEqual(call(1).call_list(), mock.mock_calls) mock = MagicMock() mock(1).method(2) self.assertEqual(call(1).method(2).call_list(), mock.mock_calls) mock = MagicMock() mock(1).method(2)(3) self.assertEqual(call(1).method(2)(3).call_list(), mock.mock_calls) mock = MagicMock() int(mock(1).method(2)(3).foo.bar.baz(4)(5)) kall = call(1).method(2)(3).foo.bar.baz(4)(5).__int__() self.assertEqual(kall.call_list(), mock.mock_calls) def test_call_any(self): self.assertEqual(call, ANY) m = MagicMock() int(m) self.assertEqual(m.mock_calls, [ANY]) self.assertEqual([ANY], m.mock_calls) def test_two_args_call(self): args = _Call(((1, 2), {'a': 3}), two=True) self.assertEqual(len(args), 2) self.assertEqual(args[0], (1, 2)) self.assertEqual(args[1], {'a': 3}) other_args = _Call(((1, 2), {'a': 3})) self.assertEqual(args, other_args) def test_call_with_name(self): self.assertEqual(_Call((), 'foo')[0], 'foo') self.assertEqual(_Call((('bar', 'barz'),),)[0], '') self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '') def test_dunder_call(self): m = MagicMock() m().foo()['bar']() self.assertEqual( m.mock_calls, [call(), call().foo(), call().foo().__getitem__('bar'), call().foo().__getitem__()()] ) m = MagicMock() m().foo()['bar'] = 1 self.assertEqual( m.mock_calls, [call(), call().foo(), call().foo().__setitem__('bar', 1)] ) m = MagicMock() iter(m().foo()) self.assertEqual( m.mock_calls, [call(), call().foo(), call().foo().__iter__()] ) class SpecSignatureTest(unittest.TestCase): def _check_someclass_mock(self, mock): self.assertRaises(AttributeError, getattr, mock, 'foo') mock.one(1, 2) mock.one.assert_called_with(1, 2) self.assertRaises(AssertionError, mock.one.assert_called_with, 3, 4) self.assertRaises(TypeError, mock.one, 1) mock.two() mock.two.assert_called_with() self.assertRaises(AssertionError, mock.two.assert_called_with, 3) self.assertRaises(TypeError, mock.two, 1) mock.three() mock.three.assert_called_with() self.assertRaises(AssertionError, mock.three.assert_called_with, 3) self.assertRaises(TypeError, mock.three, 3, 2) mock.three(1) mock.three.assert_called_with(1) mock.three(a=1) mock.three.assert_called_with(a=1) def test_basic(self): mock = create_autospec(SomeClass) self._check_someclass_mock(mock) mock = create_autospec(SomeClass()) self._check_someclass_mock(mock) def test_create_autospec_return_value(self): def f(): pass mock = create_autospec(f, return_value='foo') self.assertEqual(mock(), 'foo') class Foo(object): pass mock = create_autospec(Foo, return_value='foo') self.assertEqual(mock(), 'foo') def test_autospec_reset_mock(self): m = create_autospec(int) int(m) m.reset_mock() self.assertEqual(m.__int__.call_count, 0) def test_mocking_unbound_methods(self): class Foo(object): def foo(self, foo): pass p = patch.object(Foo, 'foo') mock_foo = p.start() Foo().foo(1) mock_foo.assert_called_with(1) def test_create_autospec_keyword_arguments(self): class Foo(object): a = 3 m = create_autospec(Foo, a='3') self.assertEqual(m.a, '3') def test_create_autospec_keyword_only_arguments(self): def foo(a, *, b=None): pass m = create_autospec(foo) m(1) m.assert_called_with(1) self.assertRaises(TypeError, m, 1, 2) m(2, b=3) m.assert_called_with(2, b=3) def test_function_as_instance_attribute(self): obj = SomeClass() def f(a): pass obj.f = f mock = create_autospec(obj) mock.f('bing') mock.f.assert_called_with('bing') def test_spec_as_list(self): # because spec as a list of strings in the mock constructor means # something very different we treat a list instance as the type. mock = create_autospec([]) mock.append('foo') mock.append.assert_called_with('foo') self.assertRaises(AttributeError, getattr, mock, 'foo') class Foo(object): foo = [] mock = create_autospec(Foo) mock.foo.append(3) mock.foo.append.assert_called_with(3) self.assertRaises(AttributeError, getattr, mock.foo, 'foo') def test_attributes(self): class Sub(SomeClass): attr = SomeClass() sub_mock = create_autospec(Sub) for mock in (sub_mock, sub_mock.attr): self._check_someclass_mock(mock) def test_spec_has_descriptor_returning_function(self): class CrazyDescriptor(object): def __get__(self, obj, type_): if obj is None: return lambda x: None class MyClass(object): some_attr = CrazyDescriptor() mock = create_autospec(MyClass) mock.some_attr(1) with self.assertRaises(TypeError): mock.some_attr() with self.assertRaises(TypeError): mock.some_attr(1, 2) def test_spec_has_function_not_in_bases(self): class CrazyClass(object): def __dir__(self): return super(CrazyClass, self).__dir__()+['crazy'] def __getattr__(self, item): if item == 'crazy': return lambda x: x raise AttributeError(item) inst = CrazyClass() with self.assertRaises(AttributeError): inst.other self.assertEqual(inst.crazy(42), 42) mock = create_autospec(inst) mock.crazy(42) with self.assertRaises(TypeError): mock.crazy() with self.assertRaises(TypeError): mock.crazy(1, 2) def test_builtin_functions_types(self): # we could replace builtin functions / methods with a function # with *args / **kwargs signature. Using the builtin method type # as a spec seems to work fairly well though. class BuiltinSubclass(list): def bar(self, arg): pass sorted = sorted attr = {} mock = create_autospec(BuiltinSubclass) mock.append(3) mock.append.assert_called_with(3) self.assertRaises(AttributeError, getattr, mock.append, 'foo') mock.bar('foo') mock.bar.assert_called_with('foo') self.assertRaises(TypeError, mock.bar, 'foo', 'bar') self.assertRaises(AttributeError, getattr, mock.bar, 'foo') mock.sorted([1, 2]) mock.sorted.assert_called_with([1, 2]) self.assertRaises(AttributeError, getattr, mock.sorted, 'foo') mock.attr.pop(3) mock.attr.pop.assert_called_with(3) self.assertRaises(AttributeError, getattr, mock.attr, 'foo') def test_method_calls(self): class Sub(SomeClass): attr = SomeClass() mock = create_autospec(Sub) mock.one(1, 2) mock.two() mock.three(3) expected = [call.one(1, 2), call.two(), call.three(3)] self.assertEqual(mock.method_calls, expected) mock.attr.one(1, 2) mock.attr.two() mock.attr.three(3) expected.extend( [call.attr.one(1, 2), call.attr.two(), call.attr.three(3)] ) self.assertEqual(mock.method_calls, expected) def test_magic_methods(self): class BuiltinSubclass(list): attr = {} mock = create_autospec(BuiltinSubclass) self.assertEqual(list(mock), []) self.assertRaises(TypeError, int, mock) self.assertRaises(TypeError, int, mock.attr) self.assertEqual(list(mock), []) self.assertIsInstance(mock['foo'], MagicMock) self.assertIsInstance(mock.attr['foo'], MagicMock) def test_spec_set(self): class Sub(SomeClass): attr = SomeClass() for spec in (Sub, Sub()): mock = create_autospec(spec, spec_set=True) self._check_someclass_mock(mock) self.assertRaises(AttributeError, setattr, mock, 'foo', 'bar') self.assertRaises(AttributeError, setattr, mock.attr, 'foo', 'bar') def test_descriptors(self): class Foo(object): @classmethod def f(cls, a, b): pass @staticmethod def g(a, b): pass class Bar(Foo): pass class Baz(SomeClass, Bar): pass for spec in (Foo, Foo(), Bar, Bar(), Baz, Baz()): mock = create_autospec(spec) mock.f(1, 2) mock.f.assert_called_once_with(1, 2) mock.g(3, 4) mock.g.assert_called_once_with(3, 4) def test_recursive(self): class A(object): def a(self): pass foo = 'foo bar baz' bar = foo A.B = A mock = create_autospec(A) mock() self.assertFalse(mock.B.called) mock.a() mock.B.a() self.assertEqual(mock.method_calls, [call.a(), call.B.a()]) self.assertIs(A.foo, A.bar) self.assertIsNot(mock.foo, mock.bar) mock.foo.lower() self.assertRaises(AssertionError, mock.bar.lower.assert_called_with) def test_spec_inheritance_for_classes(self): class Foo(object): def a(self, x): pass class Bar(object): def f(self, y): pass class_mock = create_autospec(Foo) self.assertIsNot(class_mock, class_mock()) for this_mock in class_mock, class_mock(): this_mock.a(x=5) this_mock.a.assert_called_with(x=5) this_mock.a.assert_called_with(5) self.assertRaises(TypeError, this_mock.a, 'foo', 'bar') self.assertRaises(AttributeError, getattr, this_mock, 'b') instance_mock = create_autospec(Foo()) instance_mock.a(5) instance_mock.a.assert_called_with(5) instance_mock.a.assert_called_with(x=5) self.assertRaises(TypeError, instance_mock.a, 'foo', 'bar') self.assertRaises(AttributeError, getattr, instance_mock, 'b') # The return value isn't isn't callable self.assertRaises(TypeError, instance_mock) instance_mock.Bar.f(6) instance_mock.Bar.f.assert_called_with(6) instance_mock.Bar.f.assert_called_with(y=6) self.assertRaises(AttributeError, getattr, instance_mock.Bar, 'g') instance_mock.Bar().f(6) instance_mock.Bar().f.assert_called_with(6) instance_mock.Bar().f.assert_called_with(y=6) self.assertRaises(AttributeError, getattr, instance_mock.Bar(), 'g') def test_inherit(self): class Foo(object): a = 3 Foo.Foo = Foo # class mock = create_autospec(Foo) instance = mock() self.assertRaises(AttributeError, getattr, instance, 'b') attr_instance = mock.Foo() self.assertRaises(AttributeError, getattr, attr_instance, 'b') # instance mock = create_autospec(Foo()) self.assertRaises(AttributeError, getattr, mock, 'b') self.assertRaises(TypeError, mock) # attribute instance call_result = mock.Foo() self.assertRaises(AttributeError, getattr, call_result, 'b') def test_builtins(self): # used to fail with infinite recursion create_autospec(1) create_autospec(int) create_autospec('foo') create_autospec(str) create_autospec({}) create_autospec(dict) create_autospec([]) create_autospec(list) create_autospec(set()) create_autospec(set) create_autospec(1.0) create_autospec(float) create_autospec(1j) create_autospec(complex) create_autospec(False) create_autospec(True) def test_function(self): def f(a, b): pass mock = create_autospec(f) self.assertRaises(TypeError, mock) mock(1, 2) mock.assert_called_with(1, 2) mock.assert_called_with(1, b=2) mock.assert_called_with(a=1, b=2) f.f = f mock = create_autospec(f) self.assertRaises(TypeError, mock.f) mock.f(3, 4) mock.f.assert_called_with(3, 4) mock.f.assert_called_with(a=3, b=4) def test_skip_attributeerrors(self): class Raiser(object): def __get__(self, obj, type=None): if obj is None: raise AttributeError('Can only be accessed via an instance') class RaiserClass(object): raiser = Raiser() @staticmethod def existing(a, b): return a + b self.assertEqual(RaiserClass.existing(1, 2), 3) s = create_autospec(RaiserClass) self.assertRaises(TypeError, lambda x: s.existing(1, 2, 3)) self.assertEqual(s.existing(1, 2), s.existing.return_value) self.assertRaises(AttributeError, lambda: s.nonexisting) # check we can fetch the raiser attribute and it has no spec obj = s.raiser obj.foo, obj.bar def test_signature_class(self): class Foo(object): def __init__(self, a, b=3): pass mock = create_autospec(Foo) self.assertRaises(TypeError, mock) mock(1) mock.assert_called_once_with(1) mock.assert_called_once_with(a=1) self.assertRaises(AssertionError, mock.assert_called_once_with, 2) mock(4, 5) mock.assert_called_with(4, 5) mock.assert_called_with(a=4, b=5) self.assertRaises(AssertionError, mock.assert_called_with, a=5, b=4) def test_class_with_no_init(self): # this used to raise an exception # due to trying to get a signature from object.__init__ class Foo(object): pass create_autospec(Foo) def test_signature_callable(self): class Callable(object): def __init__(self, x, y): pass def __call__(self, a): pass mock = create_autospec(Callable) mock(1, 2) mock.assert_called_once_with(1, 2) mock.assert_called_once_with(x=1, y=2) self.assertRaises(TypeError, mock, 'a') instance = mock(1, 2) self.assertRaises(TypeError, instance) instance(a='a') instance.assert_called_once_with('a') instance.assert_called_once_with(a='a') instance('a') instance.assert_called_with('a') instance.assert_called_with(a='a') mock = create_autospec(Callable(1, 2)) mock(a='a') mock.assert_called_once_with(a='a') self.assertRaises(TypeError, mock) mock('a') mock.assert_called_with('a') def test_signature_noncallable(self): class NonCallable(object): def __init__(self): pass mock = create_autospec(NonCallable) instance = mock() mock.assert_called_once_with() self.assertRaises(TypeError, mock, 'a') self.assertRaises(TypeError, instance) self.assertRaises(TypeError, instance, 'a') mock = create_autospec(NonCallable()) self.assertRaises(TypeError, mock) self.assertRaises(TypeError, mock, 'a') def test_create_autospec_none(self): class Foo(object): bar = None mock = create_autospec(Foo) none = mock.bar self.assertNotIsInstance(none, type(None)) none.foo() none.foo.assert_called_once_with() def test_autospec_functions_with_self_in_odd_place(self): class Foo(object): def f(a, self): pass a = create_autospec(Foo) a.f(10) a.f.assert_called_with(10) a.f.assert_called_with(self=10) a.f(self=10) a.f.assert_called_with(10) a.f.assert_called_with(self=10) def test_autospec_data_descriptor(self): class Descriptor(object): def __init__(self, value): self.value = value def __get__(self, obj, cls=None): return self def __set__(self, obj, value): pass class MyProperty(property): pass class Foo(object): __slots__ = ['slot'] @property def prop(self): pass @MyProperty def subprop(self): pass desc = Descriptor(42) foo = create_autospec(Foo) def check_data_descriptor(mock_attr): # Data descriptors don't have a spec. self.assertIsInstance(mock_attr, MagicMock) mock_attr(1, 2, 3) mock_attr.abc(4, 5, 6) mock_attr.assert_called_once_with(1, 2, 3) mock_attr.abc.assert_called_once_with(4, 5, 6) # property check_data_descriptor(foo.prop) # property subclass check_data_descriptor(foo.subprop) # class __slot__ check_data_descriptor(foo.slot) # plain data descriptor check_data_descriptor(foo.desc) def test_autospec_on_bound_builtin_function(self): meth = types.MethodType(time.ctime, time.time()) self.assertIsInstance(meth(), str) mocked = create_autospec(meth) # no signature, so no spec to check against mocked() mocked.assert_called_once_with() mocked.reset_mock() # but pypy gets this right: if IS_PYPY: with self.assertRaises(TypeError): mocked(4, 5, 6) else: mocked(4, 5, 6) mocked.assert_called_once_with(4, 5, 6) def test_autospec_getattr_partial_function(self): # bpo-32153 : getattr returning partial functions without # __name__ should not create AttributeError in create_autospec class Foo: def __getattr__(self, attribute): return partial(lambda name: name, attribute) proxy = Foo() autospec = create_autospec(proxy) self.assertFalse(hasattr(autospec, '__name__')) def test_spec_inspect_signature(self): def myfunc(x, y): pass mock = create_autospec(myfunc) mock(1, 2) mock(x=1, y=2) self.assertEqual(inspect.signature(mock), inspect.signature(myfunc)) self.assertEqual(mock.mock_calls, [call(1, 2), call(x=1, y=2)]) self.assertRaises(TypeError, mock, 1) def test_spec_inspect_signature_annotations(self): def foo(a: int, b: int=10, *, c:int) -> int: return a + b + c self.assertEqual(foo(1, 2 , c=3), 6) mock = create_autospec(foo) mock(1, 2, c=3) mock(1, c=3) self.assertEqual(inspect.signature(mock), inspect.signature(foo)) self.assertEqual(mock.mock_calls, [call(1, 2, c=3), call(1, c=3)]) self.assertRaises(TypeError, mock, 1) self.assertRaises(TypeError, mock, 1, 2, 3, c=4) def test_spec_function_no_name(self): func = lambda: 'nope' mock = create_autospec(func) self.assertEqual(mock.__name__, 'funcopy') def test_spec_function_assert_has_calls(self): def f(a): pass mock = create_autospec(f) mock(1) mock.assert_has_calls([call(1)]) with self.assertRaises(AssertionError): mock.assert_has_calls([call(2)]) def test_spec_function_assert_any_call(self): def f(a): pass mock = create_autospec(f) mock(1) mock.assert_any_call(1) with self.assertRaises(AssertionError): mock.assert_any_call(2) def test_spec_function_reset_mock(self): def f(a): pass rv = Mock() mock = create_autospec(f, return_value=rv) mock(1)(2) self.assertEqual(mock.mock_calls, [call(1)]) self.assertEqual(rv.mock_calls, [call(2)]) mock.reset_mock() self.assertEqual(mock.mock_calls, []) self.assertEqual(rv.mock_calls, []) class TestCallList(unittest.TestCase): def test_args_list_contains_call_list(self): mock = Mock() self.assertIsInstance(mock.call_args_list, _CallList) mock(1, 2) mock(a=3) mock(3, 4) mock(b=6) for kall in call(1, 2), call(a=3), call(3, 4), call(b=6): self.assertIn(kall, mock.call_args_list) calls = [call(a=3), call(3, 4)] self.assertIn(calls, mock.call_args_list) calls = [call(1, 2), call(a=3)] self.assertIn(calls, mock.call_args_list) calls = [call(3, 4), call(b=6)] self.assertIn(calls, mock.call_args_list) calls = [call(3, 4)] self.assertIn(calls, mock.call_args_list) self.assertNotIn(call('fish'), mock.call_args_list) self.assertNotIn([call('fish')], mock.call_args_list) def test_call_list_str(self): mock = Mock() mock(1, 2) mock.foo(a=3) mock.foo.bar().baz('fish', cat='dog') expected = ( "[call(1, 2),\n" " call.foo(a=3),\n" " call.foo.bar(),\n" " call.foo.bar().baz('fish', cat='dog')]" ) self.assertEqual(str(mock.mock_calls), expected) def test_propertymock(self): p = patch('%s.SomeClass.one' % __name__, new_callable=PropertyMock) mock = p.start() try: SomeClass.one mock.assert_called_once_with() s = SomeClass() s.one mock.assert_called_with() self.assertEqual(mock.mock_calls, [call(), call()]) s.one = 3 self.assertEqual(mock.mock_calls, [call(), call(), call(3)]) finally: p.stop() def test_propertymock_returnvalue(self): m = MagicMock() p = PropertyMock() type(m).foo = p returned = m.foo p.assert_called_once_with() self.assertIsInstance(returned, MagicMock) self.assertNotIsInstance(returned, PropertyMock) class TestCallablePredicate(unittest.TestCase): def test_type(self): for obj in [str, bytes, int, list, tuple, SomeClass]: self.assertTrue(_callable(obj)) def test_call_magic_method(self): class Callable: def __call__(self): pass instance = Callable() self.assertTrue(_callable(instance)) def test_staticmethod(self): class WithStaticMethod: @staticmethod def staticfunc(): pass self.assertTrue(_callable(WithStaticMethod.staticfunc)) def test_non_callable_staticmethod(self): class BadStaticMethod: not_callable = staticmethod(None) self.assertFalse(_callable(BadStaticMethod.not_callable)) def test_classmethod(self): class WithClassMethod: @classmethod def classfunc(cls): pass self.assertTrue(_callable(WithClassMethod.classfunc)) def test_non_callable_classmethod(self): class BadClassMethod: not_callable = classmethod(None) self.assertFalse(_callable(BadClassMethod.not_callable)) if __name__ == '__main__': unittest.main() mock-4.0.3/mock/tests/testmagicmethods.py000066400000000000000000000376051376434722300205060ustar00rootroot00000000000000import math import unittest import os from mock import AsyncMock, Mock, MagicMock from mock.backports import iscoroutinefunction from mock.mock import _magics class TestMockingMagicMethods(unittest.TestCase): def test_deleting_magic_methods(self): mock = Mock() self.assertFalse(hasattr(mock, '__getitem__')) mock.__getitem__ = Mock() self.assertTrue(hasattr(mock, '__getitem__')) del mock.__getitem__ self.assertFalse(hasattr(mock, '__getitem__')) def test_magicmock_del(self): mock = MagicMock() # before using getitem del mock.__getitem__ self.assertRaises(TypeError, lambda: mock['foo']) mock = MagicMock() # this time use it first mock['foo'] del mock.__getitem__ self.assertRaises(TypeError, lambda: mock['foo']) def test_magic_method_wrapping(self): mock = Mock() def f(self, name): return self, 'fish' mock.__getitem__ = f self.assertIsNot(mock.__getitem__, f) self.assertEqual(mock['foo'], (mock, 'fish')) self.assertEqual(mock.__getitem__('foo'), (mock, 'fish')) mock.__getitem__ = mock self.assertIs(mock.__getitem__, mock) def test_magic_methods_isolated_between_mocks(self): mock1 = Mock() mock2 = Mock() mock1.__iter__ = Mock(return_value=iter([])) self.assertEqual(list(mock1), []) self.assertRaises(TypeError, lambda: list(mock2)) def test_repr(self): mock = Mock() self.assertEqual(repr(mock), "" % id(mock)) mock.__repr__ = lambda s: 'foo' self.assertEqual(repr(mock), 'foo') def test_str(self): mock = Mock() self.assertEqual(str(mock), object.__str__(mock)) mock.__str__ = lambda s: 'foo' self.assertEqual(str(mock), 'foo') def test_dict_methods(self): mock = Mock() self.assertRaises(TypeError, lambda: mock['foo']) def _del(): del mock['foo'] def _set(): mock['foo'] = 3 self.assertRaises(TypeError, _del) self.assertRaises(TypeError, _set) _dict = {} def getitem(s, name): return _dict[name] def setitem(s, name, value): _dict[name] = value def delitem(s, name): del _dict[name] mock.__setitem__ = setitem mock.__getitem__ = getitem mock.__delitem__ = delitem self.assertRaises(KeyError, lambda: mock['foo']) mock['foo'] = 'bar' self.assertEqual(_dict, {'foo': 'bar'}) self.assertEqual(mock['foo'], 'bar') del mock['foo'] self.assertEqual(_dict, {}) def test_numeric(self): original = mock = Mock() mock.value = 0 self.assertRaises(TypeError, lambda: mock + 3) def add(self, other): mock.value += other return self mock.__add__ = add self.assertEqual(mock + 3, mock) self.assertEqual(mock.value, 3) del mock.__add__ def iadd(mock): mock += 3 self.assertRaises(TypeError, iadd, mock) mock.__iadd__ = add mock += 6 self.assertEqual(mock, original) self.assertEqual(mock.value, 9) self.assertRaises(TypeError, lambda: 3 + mock) mock.__radd__ = add self.assertEqual(7 + mock, mock) self.assertEqual(mock.value, 16) def test_division(self): original = mock = Mock() mock.value = 32 self.assertRaises(TypeError, lambda: mock / 2) def truediv(self, other): mock.value /= other return self mock.__truediv__ = truediv self.assertEqual(mock / 2, mock) self.assertEqual(mock.value, 16) del mock.__truediv__ def itruediv(mock): mock /= 4 self.assertRaises(TypeError, itruediv, mock) mock.__itruediv__ = truediv mock /= 8 self.assertEqual(mock, original) self.assertEqual(mock.value, 2) self.assertRaises(TypeError, lambda: 8 / mock) mock.__rtruediv__ = truediv self.assertEqual(0.5 / mock, mock) self.assertEqual(mock.value, 4) def test_hash(self): mock = Mock() # test delegation self.assertEqual(hash(mock), Mock.__hash__(mock)) def _hash(s): return 3 mock.__hash__ = _hash self.assertEqual(hash(mock), 3) def test_nonzero(self): m = Mock() self.assertTrue(bool(m)) m.__bool__ = lambda s: False self.assertFalse(bool(m)) def test_comparison(self): mock = Mock() def comp(s, o): return True mock.__lt__ = mock.__gt__ = mock.__le__ = mock.__ge__ = comp self. assertTrue(mock < 3) self. assertTrue(mock > 3) self. assertTrue(mock <= 3) self. assertTrue(mock >= 3) self.assertRaises(TypeError, lambda: MagicMock() < object()) self.assertRaises(TypeError, lambda: object() < MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() < MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() > object()) self.assertRaises(TypeError, lambda: object() > MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() > MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() <= object()) self.assertRaises(TypeError, lambda: object() <= MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() <= MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() >= object()) self.assertRaises(TypeError, lambda: object() >= MagicMock()) self.assertRaises(TypeError, lambda: MagicMock() >= MagicMock()) def test_equality(self): for mock in Mock(), MagicMock(): self.assertEqual(mock == mock, True) self.assertIsInstance(mock == mock, bool) self.assertEqual(mock != mock, False) self.assertIsInstance(mock != mock, bool) self.assertEqual(mock == object(), False) self.assertEqual(mock != object(), True) def eq(self, other): return other == 3 mock.__eq__ = eq self.assertTrue(mock == 3) self.assertFalse(mock == 4) def ne(self, other): return other == 3 mock.__ne__ = ne self.assertTrue(mock != 3) self.assertFalse(mock != 4) mock = MagicMock() mock.__eq__.return_value = True self.assertIsInstance(mock == 3, bool) self.assertEqual(mock == 3, True) mock.__ne__.return_value = False self.assertIsInstance(mock != 3, bool) self.assertEqual(mock != 3, False) def test_len_contains_iter(self): mock = Mock() self.assertRaises(TypeError, len, mock) self.assertRaises(TypeError, iter, mock) self.assertRaises(TypeError, lambda: 'foo' in mock) mock.__len__ = lambda s: 6 self.assertEqual(len(mock), 6) mock.__contains__ = lambda s, o: o == 3 self.assertIn(3, mock) self.assertNotIn(6, mock) mock.__iter__ = lambda s: iter('foobarbaz') self.assertEqual(list(mock), list('foobarbaz')) def test_magicmock(self): mock = MagicMock() mock.__iter__.return_value = iter([1, 2, 3]) self.assertEqual(list(mock), [1, 2, 3]) getattr(mock, '__bool__').return_value = False self.assertFalse(hasattr(mock, '__nonzero__')) self.assertFalse(bool(mock)) for entry in _magics: self.assertTrue(hasattr(mock, entry)) self.assertFalse(hasattr(mock, '__imaginary__')) def test_magic_mock_equality(self): mock = MagicMock() self.assertIsInstance(mock == object(), bool) self.assertIsInstance(mock != object(), bool) self.assertEqual(mock == object(), False) self.assertEqual(mock != object(), True) self.assertEqual(mock == mock, True) self.assertEqual(mock != mock, False) def test_asyncmock_defaults(self): mock = AsyncMock() self.assertEqual(int(mock), 1) self.assertEqual(complex(mock), 1j) self.assertEqual(float(mock), 1.0) self.assertNotIn(object(), mock) self.assertEqual(len(mock), 0) self.assertEqual(list(mock), []) self.assertEqual(hash(mock), object.__hash__(mock)) self.assertEqual(str(mock), object.__str__(mock)) self.assertTrue(bool(mock)) self.assertEqual(round(mock), mock.__round__()) self.assertEqual(math.trunc(mock), mock.__trunc__()) self.assertEqual(math.floor(mock), mock.__floor__()) self.assertEqual(math.ceil(mock), mock.__ceil__()) self.assertTrue(iscoroutinefunction(mock.__aexit__)) self.assertTrue(iscoroutinefunction(mock.__aenter__)) self.assertIsInstance(mock.__aenter__, AsyncMock) self.assertIsInstance(mock.__aexit__, AsyncMock) # in Python 3 oct and hex use __index__ # so these tests are for __index__ in py3k self.assertEqual(oct(mock), '0o1') self.assertEqual(hex(mock), '0x1') # how to test __sizeof__ ? def test_magicmock_defaults(self): mock = MagicMock() self.assertEqual(int(mock), 1) self.assertEqual(complex(mock), 1j) self.assertEqual(float(mock), 1.0) self.assertNotIn(object(), mock) self.assertEqual(len(mock), 0) self.assertEqual(list(mock), []) self.assertEqual(hash(mock), object.__hash__(mock)) self.assertEqual(str(mock), object.__str__(mock)) self.assertTrue(bool(mock)) self.assertEqual(round(mock), mock.__round__()) self.assertEqual(math.trunc(mock), mock.__trunc__()) self.assertEqual(math.floor(mock), mock.__floor__()) self.assertEqual(math.ceil(mock), mock.__ceil__()) self.assertTrue(iscoroutinefunction(mock.__aexit__)) self.assertTrue(iscoroutinefunction(mock.__aenter__)) self.assertIsInstance(mock.__aenter__, AsyncMock) self.assertIsInstance(mock.__aexit__, AsyncMock) # in Python 3 oct and hex use __index__ # so these tests are for __index__ in py3k self.assertEqual(oct(mock), '0o1') self.assertEqual(hex(mock), '0x1') # how to test __sizeof__ ? def test_magic_methods_fspath(self): mock = MagicMock() expected_path = mock.__fspath__() mock.reset_mock() self.assertEqual(os.fspath(mock), expected_path) mock.__fspath__.assert_called_once() def test_magic_methods_and_spec(self): class Iterable(object): def __iter__(self): pass mock = Mock(spec=Iterable) self.assertRaises(AttributeError, lambda: mock.__iter__) mock.__iter__ = Mock(return_value=iter([])) self.assertEqual(list(mock), []) class NonIterable(object): pass mock = Mock(spec=NonIterable) self.assertRaises(AttributeError, lambda: mock.__iter__) def set_int(): mock.__int__ = Mock(return_value=iter([])) self.assertRaises(AttributeError, set_int) mock = MagicMock(spec=Iterable) self.assertEqual(list(mock), []) self.assertRaises(AttributeError, set_int) def test_magic_methods_and_spec_set(self): class Iterable(object): def __iter__(self): pass mock = Mock(spec_set=Iterable) self.assertRaises(AttributeError, lambda: mock.__iter__) mock.__iter__ = Mock(return_value=iter([])) self.assertEqual(list(mock), []) class NonIterable(object): pass mock = Mock(spec_set=NonIterable) self.assertRaises(AttributeError, lambda: mock.__iter__) def set_int(): mock.__int__ = Mock(return_value=iter([])) self.assertRaises(AttributeError, set_int) mock = MagicMock(spec_set=Iterable) self.assertEqual(list(mock), []) self.assertRaises(AttributeError, set_int) def test_setting_unsupported_magic_method(self): mock = MagicMock() def set_setattr(): mock.__setattr__ = lambda self, name: None self.assertRaisesRegex(AttributeError, "Attempting to set unsupported magic method '__setattr__'.", set_setattr ) def test_attributes_and_return_value(self): mock = MagicMock() attr = mock.foo def _get_type(obj): # the type of every mock (or magicmock) is a custom subclass # so the real type is the second in the mro return type(obj).__mro__[1] self.assertEqual(_get_type(attr), MagicMock) returned = mock() self.assertEqual(_get_type(returned), MagicMock) def test_magic_methods_are_magic_mocks(self): mock = MagicMock() self.assertIsInstance(mock.__getitem__, MagicMock) mock[1][2].__getitem__.return_value = 3 self.assertEqual(mock[1][2][3], 3) def test_magic_method_reset_mock(self): mock = MagicMock() str(mock) self.assertTrue(mock.__str__.called) mock.reset_mock() self.assertFalse(mock.__str__.called) def test_dir(self): # overriding the default implementation for mock in Mock(), MagicMock(): def _dir(self): return ['foo'] mock.__dir__ = _dir self.assertEqual(dir(mock), ['foo']) def test_bound_methods(self): m = Mock() # XXXX should this be an expected failure instead? # this seems like it should work, but is hard to do without introducing # other api inconsistencies. Failure message could be better though. m.__iter__ = [3].__iter__ self.assertRaises(TypeError, iter, m) def test_magic_method_type(self): class Foo(MagicMock): pass foo = Foo() self.assertIsInstance(foo.__int__, Foo) def test_descriptor_from_class(self): m = MagicMock() type(m).__str__.return_value = 'foo' self.assertEqual(str(m), 'foo') def test_iterable_as_iter_return_value(self): m = MagicMock() m.__iter__.return_value = [1, 2, 3] self.assertEqual(list(m), [1, 2, 3]) self.assertEqual(list(m), [1, 2, 3]) m.__iter__.return_value = iter([4, 5, 6]) self.assertEqual(list(m), [4, 5, 6]) self.assertEqual(list(m), []) def test_matmul(self): m = MagicMock() self.assertIsInstance(m @ 1, MagicMock) m.__matmul__.return_value = 42 m.__rmatmul__.return_value = 666 m.__imatmul__.return_value = 24 self.assertEqual(m @ 1, 42) self.assertEqual(1 @ m, 666) m @= 24 self.assertEqual(m, 24) def test_divmod_and_rdivmod(self): m = MagicMock() self.assertIsInstance(divmod(5, m), MagicMock) m.__divmod__.return_value = (2, 1) self.assertEqual(divmod(m, 2), (2, 1)) m = MagicMock() foo = divmod(2, m) self.assertIsInstance(foo, MagicMock) foo_direct = m.__divmod__(2) self.assertIsInstance(foo_direct, MagicMock) bar = divmod(m, 2) self.assertIsInstance(bar, MagicMock) bar_direct = m.__rdivmod__(2) self.assertIsInstance(bar_direct, MagicMock) # http://bugs.python.org/issue23310 # Check if you can change behaviour of magic methods in MagicMock init def test_magic_in_initialization(self): m = MagicMock(**{'__str__.return_value': "12"}) self.assertEqual(str(m), "12") def test_changing_magic_set_in_initialization(self): m = MagicMock(**{'__str__.return_value': "12"}) m.__str__.return_value = "13" self.assertEqual(str(m), "13") m = MagicMock(**{'__str__.return_value': "12"}) m.configure_mock(**{'__str__.return_value': "14"}) self.assertEqual(str(m), "14") if __name__ == '__main__': unittest.main() mock-4.0.3/mock/tests/testmock.py000066400000000000000000002151211376434722300167620ustar00rootroot00000000000000import copy import re import sys import tempfile import unittest from mock.tests.support import ALWAYS_EQ from mock.tests.support import is_instance from mock import ( call, DEFAULT, patch, sentinel, MagicMock, Mock, NonCallableMock, NonCallableMagicMock, AsyncMock, create_autospec, mock ) from mock.mock import _Call, _CallList class Iter(object): def __init__(self): self.thing = iter(['this', 'is', 'an', 'iter']) def __iter__(self): return self def next(self): return next(self.thing) __next__ = next class Something(object): def meth(self, a, b, c, d=None): pass @classmethod def cmeth(cls, a, b, c, d=None): pass @staticmethod def smeth(a, b, c, d=None): pass def something(a): pass class MockTest(unittest.TestCase): def test_all(self): # if __all__ is badly defined then import * will raise an error # We have to exec it because you can't import * inside a method # in Python 3 exec("from unittest.mock import *") def test_constructor(self): mock = Mock() self.assertFalse(mock.called, "called not initialised correctly") self.assertEqual(mock.call_count, 0, "call_count not initialised correctly") self.assertTrue(is_instance(mock.return_value, Mock), "return_value not initialised correctly") self.assertEqual(mock.call_args, None, "call_args not initialised correctly") self.assertEqual(mock.call_args_list, [], "call_args_list not initialised correctly") self.assertEqual(mock.method_calls, [], "method_calls not initialised correctly") # Can't use hasattr for this test as it always returns True on a mock self.assertNotIn('_items', mock.__dict__, "default mock should not have '_items' attribute") self.assertIsNone(mock._mock_parent, "parent not initialised correctly") self.assertIsNone(mock._mock_methods, "methods not initialised correctly") self.assertEqual(mock._mock_children, {}, "children not initialised incorrectly") def test_return_value_in_constructor(self): mock = Mock(return_value=None) self.assertIsNone(mock.return_value, "return value in constructor not honoured") def test_change_return_value_via_delegate(self): def f(): pass mock = create_autospec(f) mock.mock.return_value = 1 self.assertEqual(mock(), 1) def test_change_side_effect_via_delegate(self): def f(): pass mock = create_autospec(f) mock.mock.side_effect = TypeError() with self.assertRaises(TypeError): mock() def test_repr(self): mock = Mock(name='foo') self.assertIn('foo', repr(mock)) self.assertIn("'%s'" % id(mock), repr(mock)) mocks = [(Mock(), 'mock'), (Mock(name='bar'), 'bar')] for mock, name in mocks: self.assertIn('%s.bar' % name, repr(mock.bar)) self.assertIn('%s.foo()' % name, repr(mock.foo())) self.assertIn('%s.foo().bing' % name, repr(mock.foo().bing)) self.assertIn('%s()' % name, repr(mock())) self.assertIn('%s()()' % name, repr(mock()())) self.assertIn('%s()().foo.bar.baz().bing' % name, repr(mock()().foo.bar.baz().bing)) def test_repr_with_spec(self): class X(object): pass mock = Mock(spec=X) self.assertIn(" spec='X' ", repr(mock)) mock = Mock(spec=X()) self.assertIn(" spec='X' ", repr(mock)) mock = Mock(spec_set=X) self.assertIn(" spec_set='X' ", repr(mock)) mock = Mock(spec_set=X()) self.assertIn(" spec_set='X' ", repr(mock)) mock = Mock(spec=X, name='foo') self.assertIn(" spec='X' ", repr(mock)) self.assertIn(" name='foo' ", repr(mock)) mock = Mock(name='foo') self.assertNotIn("spec", repr(mock)) mock = Mock() self.assertNotIn("spec", repr(mock)) mock = Mock(spec=['foo']) self.assertNotIn("spec", repr(mock)) def test_side_effect(self): mock = Mock() def effect(*args, **kwargs): raise SystemError('kablooie') mock.side_effect = effect self.assertRaises(SystemError, mock, 1, 2, fish=3) mock.assert_called_with(1, 2, fish=3) results = [1, 2, 3] def effect(): return results.pop() mock.side_effect = effect self.assertEqual([mock(), mock(), mock()], [3, 2, 1], "side effect not used correctly") mock = Mock(side_effect=sentinel.SideEffect) self.assertEqual(mock.side_effect, sentinel.SideEffect, "side effect in constructor not used") def side_effect(): return DEFAULT mock = Mock(side_effect=side_effect, return_value=sentinel.RETURN) self.assertEqual(mock(), sentinel.RETURN) def test_autospec_side_effect(self): # Test for issue17826 results = [1, 2, 3] def effect(): return results.pop() def f(): pass mock = create_autospec(f) mock.side_effect = [1, 2, 3] self.assertEqual([mock(), mock(), mock()], [1, 2, 3], "side effect not used correctly in create_autospec") # Test where side effect is a callable results = [1, 2, 3] mock = create_autospec(f) mock.side_effect = effect self.assertEqual([mock(), mock(), mock()], [3, 2, 1], "callable side effect not used correctly") def test_autospec_side_effect_exception(self): # Test for issue 23661 def f(): pass mock = create_autospec(f) mock.side_effect = ValueError('Bazinga!') self.assertRaisesRegex(ValueError, 'Bazinga!', mock) def test_reset_mock(self): parent = Mock() spec = ["something"] mock = Mock(name="child", parent=parent, spec=spec) mock(sentinel.Something, something=sentinel.SomethingElse) something = mock.something mock.something() mock.side_effect = sentinel.SideEffect return_value = mock.return_value return_value() mock.reset_mock() self.assertEqual(mock._mock_name, "child", "name incorrectly reset") self.assertEqual(mock._mock_parent, parent, "parent incorrectly reset") self.assertEqual(mock._mock_methods, spec, "methods incorrectly reset") self.assertFalse(mock.called, "called not reset") self.assertEqual(mock.call_count, 0, "call_count not reset") self.assertEqual(mock.call_args, None, "call_args not reset") self.assertEqual(mock.call_args_list, [], "call_args_list not reset") self.assertEqual(mock.method_calls, [], "method_calls not initialised correctly: %r != %r" % (mock.method_calls, [])) self.assertEqual(mock.mock_calls, []) self.assertEqual(mock.side_effect, sentinel.SideEffect, "side_effect incorrectly reset") self.assertEqual(mock.return_value, return_value, "return_value incorrectly reset") self.assertFalse(return_value.called, "return value mock not reset") self.assertEqual(mock._mock_children, {'something': something}, "children reset incorrectly") self.assertEqual(mock.something, something, "children incorrectly cleared") self.assertFalse(mock.something.called, "child not reset") def test_reset_mock_recursion(self): mock = Mock() mock.return_value = mock # used to cause recursion mock.reset_mock() def test_reset_mock_on_mock_open_issue_18622(self): a = mock.mock_open() a.reset_mock() def test_call(self): mock = Mock() self.assertTrue(is_instance(mock.return_value, Mock), "Default return_value should be a Mock") result = mock() self.assertEqual(mock(), result, "different result from consecutive calls") mock.reset_mock() ret_val = mock(sentinel.Arg) self.assertTrue(mock.called, "called not set") self.assertEqual(mock.call_count, 1, "call_count incorrect") self.assertEqual(mock.call_args, ((sentinel.Arg,), {}), "call_args not set") self.assertEqual(mock.call_args.args, (sentinel.Arg,), "call_args not set") self.assertEqual(mock.call_args.kwargs, {}, "call_args not set") self.assertEqual(mock.call_args_list, [((sentinel.Arg,), {})], "call_args_list not initialised correctly") mock.return_value = sentinel.ReturnValue ret_val = mock(sentinel.Arg, key=sentinel.KeyArg) self.assertEqual(ret_val, sentinel.ReturnValue, "incorrect return value") self.assertEqual(mock.call_count, 2, "call_count incorrect") self.assertEqual(mock.call_args, ((sentinel.Arg,), {'key': sentinel.KeyArg}), "call_args not set") self.assertEqual(mock.call_args_list, [ ((sentinel.Arg,), {}), ((sentinel.Arg,), {'key': sentinel.KeyArg}) ], "call_args_list not set") def test_call_args_comparison(self): mock = Mock() mock() mock(sentinel.Arg) mock(kw=sentinel.Kwarg) mock(sentinel.Arg, kw=sentinel.Kwarg) self.assertEqual(mock.call_args_list, [ (), ((sentinel.Arg,),), ({"kw": sentinel.Kwarg},), ((sentinel.Arg,), {"kw": sentinel.Kwarg}) ]) self.assertEqual(mock.call_args, ((sentinel.Arg,), {"kw": sentinel.Kwarg})) self.assertEqual(mock.call_args.args, (sentinel.Arg,)) self.assertEqual(mock.call_args.kwargs, {"kw": sentinel.Kwarg}) # Comparing call_args to a long sequence should not raise # an exception. See issue 24857. self.assertFalse(mock.call_args == "a long sequence") def test_calls_equal_with_any(self): # Check that equality and non-equality is consistent even when # comparing with mock.ANY mm = mock.MagicMock() self.assertTrue(mm == mm) self.assertFalse(mm != mm) self.assertFalse(mm == mock.MagicMock()) self.assertTrue(mm != mock.MagicMock()) self.assertTrue(mm == mock.ANY) self.assertFalse(mm != mock.ANY) self.assertTrue(mock.ANY == mm) self.assertFalse(mock.ANY != mm) self.assertTrue(mm == ALWAYS_EQ) self.assertFalse(mm != ALWAYS_EQ) call1 = mock.call(mock.MagicMock()) call2 = mock.call(mock.ANY) self.assertTrue(call1 == call2) self.assertFalse(call1 != call2) self.assertTrue(call2 == call1) self.assertFalse(call2 != call1) self.assertTrue(call1 == ALWAYS_EQ) self.assertFalse(call1 != ALWAYS_EQ) self.assertFalse(call1 == 1) self.assertTrue(call1 != 1) def test_assert_called_with(self): mock = Mock() mock() # Will raise an exception if it fails mock.assert_called_with() self.assertRaises(AssertionError, mock.assert_called_with, 1) mock.reset_mock() self.assertRaises(AssertionError, mock.assert_called_with) mock(1, 2, 3, a='fish', b='nothing') mock.assert_called_with(1, 2, 3, a='fish', b='nothing') def test_assert_called_with_any(self): m = MagicMock() m(MagicMock()) m.assert_called_with(mock.ANY) def test_assert_called_with_function_spec(self): def f(a, b, c, d=None): pass mock = Mock(spec=f) mock(1, b=2, c=3) mock.assert_called_with(1, 2, 3) mock.assert_called_with(a=1, b=2, c=3) self.assertRaises(AssertionError, mock.assert_called_with, 1, b=3, c=2) # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_called_with(e=8) self.assertIsInstance(cm.exception.__cause__, TypeError) def test_assert_called_with_method_spec(self): def _check(mock): mock(1, b=2, c=3) mock.assert_called_with(1, 2, 3) mock.assert_called_with(a=1, b=2, c=3) self.assertRaises(AssertionError, mock.assert_called_with, 1, b=3, c=2) mock = Mock(spec=Something().meth) _check(mock) mock = Mock(spec=Something.cmeth) _check(mock) mock = Mock(spec=Something().cmeth) _check(mock) mock = Mock(spec=Something.smeth) _check(mock) mock = Mock(spec=Something().smeth) _check(mock) def test_assert_called_exception_message(self): msg = "Expected '{0}' to have been called" with self.assertRaisesRegex(AssertionError, msg.format('mock')): Mock().assert_called() with self.assertRaisesRegex(AssertionError, msg.format('test_name')): Mock(name="test_name").assert_called() def test_assert_called_once_with(self): mock = Mock() mock() # Will raise an exception if it fails mock.assert_called_once_with() mock() self.assertRaises(AssertionError, mock.assert_called_once_with) mock.reset_mock() self.assertRaises(AssertionError, mock.assert_called_once_with) mock('foo', 'bar', baz=2) mock.assert_called_once_with('foo', 'bar', baz=2) mock.reset_mock() mock('foo', 'bar', baz=2) self.assertRaises( AssertionError, lambda: mock.assert_called_once_with('bob', 'bar', baz=2) ) def test_assert_called_once_with_call_list(self): m = Mock() m(1) m(2) self.assertRaisesRegex(AssertionError, re.escape("Calls: [call(1), call(2)]"), lambda: m.assert_called_once_with(2)) def test_assert_called_once_with_function_spec(self): def f(a, b, c, d=None): pass mock = Mock(spec=f) mock(1, b=2, c=3) mock.assert_called_once_with(1, 2, 3) mock.assert_called_once_with(a=1, b=2, c=3) self.assertRaises(AssertionError, mock.assert_called_once_with, 1, b=3, c=2) # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_called_once_with(e=8) self.assertIsInstance(cm.exception.__cause__, TypeError) # Mock called more than once => always fails mock(4, 5, 6) self.assertRaises(AssertionError, mock.assert_called_once_with, 1, 2, 3) self.assertRaises(AssertionError, mock.assert_called_once_with, 4, 5, 6) def test_attribute_access_returns_mocks(self): mock = Mock() something = mock.something self.assertTrue(is_instance(something, Mock), "attribute isn't a mock") self.assertEqual(mock.something, something, "different attributes returned for same name") # Usage example mock = Mock() mock.something.return_value = 3 self.assertEqual(mock.something(), 3, "method returned wrong value") self.assertTrue(mock.something.called, "method didn't record being called") def test_attributes_have_name_and_parent_set(self): mock = Mock() something = mock.something self.assertEqual(something._mock_name, "something", "attribute name not set correctly") self.assertEqual(something._mock_parent, mock, "attribute parent not set correctly") def test_method_calls_recorded(self): mock = Mock() mock.something(3, fish=None) mock.something_else.something(6, cake=sentinel.Cake) self.assertEqual(mock.something_else.method_calls, [("something", (6,), {'cake': sentinel.Cake})], "method calls not recorded correctly") self.assertEqual(mock.method_calls, [ ("something", (3,), {'fish': None}), ("something_else.something", (6,), {'cake': sentinel.Cake}) ], "method calls not recorded correctly") def test_method_calls_compare_easily(self): mock = Mock() mock.something() self.assertEqual(mock.method_calls, [('something',)]) self.assertEqual(mock.method_calls, [('something', (), {})]) mock = Mock() mock.something('different') self.assertEqual(mock.method_calls, [('something', ('different',))]) self.assertEqual(mock.method_calls, [('something', ('different',), {})]) mock = Mock() mock.something(x=1) self.assertEqual(mock.method_calls, [('something', {'x': 1})]) self.assertEqual(mock.method_calls, [('something', (), {'x': 1})]) mock = Mock() mock.something('different', some='more') self.assertEqual(mock.method_calls, [ ('something', ('different',), {'some': 'more'}) ]) def test_only_allowed_methods_exist(self): for spec in ['something'], ('something',): for arg in 'spec', 'spec_set': mock = Mock(**{arg: spec}) # this should be allowed mock.something self.assertRaisesRegex( AttributeError, "Mock object has no attribute 'something_else'", getattr, mock, 'something_else' ) def test_from_spec(self): class Something(object): x = 3 __something__ = None def y(self): pass def test_attributes(mock): # should work mock.x mock.y mock.__something__ self.assertRaisesRegex( AttributeError, "Mock object has no attribute 'z'", getattr, mock, 'z' ) self.assertRaisesRegex( AttributeError, "Mock object has no attribute '__foobar__'", getattr, mock, '__foobar__' ) test_attributes(Mock(spec=Something)) test_attributes(Mock(spec=Something())) def test_wraps_calls(self): real = Mock() mock = Mock(wraps=real) self.assertEqual(mock(), real()) real.reset_mock() mock(1, 2, fish=3) real.assert_called_with(1, 2, fish=3) def test_wraps_prevents_automatic_creation_of_mocks(self): class Real(object): pass real = Real() mock = Mock(wraps=real) self.assertRaises(AttributeError, lambda: mock.new_attr()) def test_wraps_call_with_nondefault_return_value(self): real = Mock() mock = Mock(wraps=real) mock.return_value = 3 self.assertEqual(mock(), 3) self.assertFalse(real.called) def test_wraps_attributes(self): class Real(object): attribute = Mock() real = Real() mock = Mock(wraps=real) self.assertEqual(mock.attribute(), real.attribute()) self.assertRaises(AttributeError, lambda: mock.fish) self.assertNotEqual(mock.attribute, real.attribute) result = mock.attribute.frog(1, 2, fish=3) Real.attribute.frog.assert_called_with(1, 2, fish=3) self.assertEqual(result, Real.attribute.frog()) def test_customize_wrapped_object_with_side_effect_iterable_with_default(self): class Real(object): def method(self): return sentinel.ORIGINAL_VALUE real = Real() mock = Mock(wraps=real) mock.method.side_effect = [sentinel.VALUE1, DEFAULT] self.assertEqual(mock.method(), sentinel.VALUE1) self.assertEqual(mock.method(), sentinel.ORIGINAL_VALUE) self.assertRaises(StopIteration, mock.method) def test_customize_wrapped_object_with_side_effect_iterable(self): class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.side_effect = [sentinel.VALUE1, sentinel.VALUE2] self.assertEqual(mock.method(), sentinel.VALUE1) self.assertEqual(mock.method(), sentinel.VALUE2) self.assertRaises(StopIteration, mock.method) def test_customize_wrapped_object_with_side_effect_exception(self): class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.side_effect = RuntimeError self.assertRaises(RuntimeError, mock.method) def test_customize_wrapped_object_with_side_effect_function(self): class Real(object): def method(self): pass def side_effect(): return sentinel.VALUE real = Real() mock = Mock(wraps=real) mock.method.side_effect = side_effect self.assertEqual(mock.method(), sentinel.VALUE) def test_customize_wrapped_object_with_return_value(self): class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.return_value = sentinel.VALUE self.assertEqual(mock.method(), sentinel.VALUE) def test_customize_wrapped_object_with_return_value_and_side_effect(self): # side_effect should always take precedence over return_value. class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.side_effect = [sentinel.VALUE1, sentinel.VALUE2] mock.method.return_value = sentinel.WRONG_VALUE self.assertEqual(mock.method(), sentinel.VALUE1) self.assertEqual(mock.method(), sentinel.VALUE2) self.assertRaises(StopIteration, mock.method) def test_customize_wrapped_object_with_return_value_and_side_effect2(self): # side_effect can return DEFAULT to default to return_value class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.side_effect = lambda: DEFAULT mock.method.return_value = sentinel.VALUE self.assertEqual(mock.method(), sentinel.VALUE) def test_customize_wrapped_object_with_return_value_and_side_effect_default(self): class Real(object): def method(self): pass real = Real() mock = Mock(wraps=real) mock.method.side_effect = [sentinel.VALUE1, DEFAULT] mock.method.return_value = sentinel.RETURN self.assertEqual(mock.method(), sentinel.VALUE1) self.assertEqual(mock.method(), sentinel.RETURN) self.assertRaises(StopIteration, mock.method) def test_magic_method_wraps_dict(self): # bpo-25597: MagicMock with wrap doesn't call wrapped object's # method for magic methods with default values. data = {'foo': 'bar'} wrapped_dict = MagicMock(wraps=data) self.assertEqual(wrapped_dict.get('foo'), 'bar') # Accessing key gives a MagicMock self.assertIsInstance(wrapped_dict['foo'], MagicMock) # __contains__ method has a default value of False self.assertFalse('foo' in wrapped_dict) # return_value is non-sentinel and takes precedence over wrapped value. wrapped_dict.get.return_value = 'return_value' self.assertEqual(wrapped_dict.get('foo'), 'return_value') # return_value is sentinel and hence wrapped value is returned. wrapped_dict.get.return_value = sentinel.DEFAULT self.assertEqual(wrapped_dict.get('foo'), 'bar') self.assertEqual(wrapped_dict.get('baz'), None) self.assertIsInstance(wrapped_dict['baz'], MagicMock) self.assertFalse('bar' in wrapped_dict) data['baz'] = 'spam' self.assertEqual(wrapped_dict.get('baz'), 'spam') self.assertIsInstance(wrapped_dict['baz'], MagicMock) self.assertFalse('bar' in wrapped_dict) del data['baz'] self.assertEqual(wrapped_dict.get('baz'), None) def test_magic_method_wraps_class(self): class Foo: def __getitem__(self, index): return index def __custom_method__(self): return "foo" klass = MagicMock(wraps=Foo) obj = klass() self.assertEqual(obj.__getitem__(2), 2) self.assertEqual(obj[2], 2) self.assertEqual(obj.__custom_method__(), "foo") def test_exceptional_side_effect(self): mock = Mock(side_effect=AttributeError) self.assertRaises(AttributeError, mock) mock = Mock(side_effect=AttributeError('foo')) self.assertRaises(AttributeError, mock) def test_baseexceptional_side_effect(self): mock = Mock(side_effect=KeyboardInterrupt) self.assertRaises(KeyboardInterrupt, mock) mock = Mock(side_effect=KeyboardInterrupt('foo')) self.assertRaises(KeyboardInterrupt, mock) def test_assert_called_with_message(self): mock = Mock() self.assertRaisesRegex(AssertionError, 'not called', mock.assert_called_with) def test_assert_called_once_with_message(self): mock = Mock(name='geoffrey') self.assertRaisesRegex(AssertionError, r"Expected 'geoffrey' to be called once\.", mock.assert_called_once_with) def test__name__(self): mock = Mock() self.assertRaises(AttributeError, lambda: mock.__name__) mock.__name__ = 'foo' self.assertEqual(mock.__name__, 'foo') def test_spec_list_subclass(self): class Sub(list): pass mock = Mock(spec=Sub(['foo'])) mock.append(3) mock.append.assert_called_with(3) self.assertRaises(AttributeError, getattr, mock, 'foo') def test_spec_class(self): class X(object): pass mock = Mock(spec=X) self.assertIsInstance(mock, X) mock = Mock(spec=X()) self.assertIsInstance(mock, X) self.assertIs(mock.__class__, X) self.assertEqual(Mock().__class__.__name__, 'Mock') mock = Mock(spec_set=X) self.assertIsInstance(mock, X) mock = Mock(spec_set=X()) self.assertIsInstance(mock, X) def test_spec_class_no_object_base(self): class X: pass mock = Mock(spec=X) self.assertIsInstance(mock, X) mock = Mock(spec=X()) self.assertIsInstance(mock, X) self.assertIs(mock.__class__, X) self.assertEqual(Mock().__class__.__name__, 'Mock') mock = Mock(spec_set=X) self.assertIsInstance(mock, X) mock = Mock(spec_set=X()) self.assertIsInstance(mock, X) def test_setting_attribute_with_spec_set(self): class X(object): y = 3 mock = Mock(spec=X) mock.x = 'foo' mock = Mock(spec_set=X) def set_attr(): mock.x = 'foo' mock.y = 'foo' self.assertRaises(AttributeError, set_attr) def test_copy(self): current = sys.getrecursionlimit() self.addCleanup(sys.setrecursionlimit, current) # can't use sys.maxint as this doesn't exist in Python 3 sys.setrecursionlimit(int(10e8)) # this segfaults without the fix in place copy.copy(Mock()) def test_subclass_with_properties(self): class SubClass(Mock): def _get(self): return 3 def _set(self, value): raise NameError('strange error') some_attribute = property(_get, _set) s = SubClass(spec_set=SubClass) self.assertEqual(s.some_attribute, 3) def test(): s.some_attribute = 3 self.assertRaises(NameError, test) def test(): s.foo = 'bar' self.assertRaises(AttributeError, test) def test_setting_call(self): mock = Mock() def __call__(self, a): self._increment_mock_call(a) return self._mock_call(a) type(mock).__call__ = __call__ mock('one') mock.assert_called_with('one') self.assertRaises(TypeError, mock, 'one', 'two') def test_dir(self): mock = Mock() attrs = set(dir(mock)) type_attrs = set([m for m in dir(Mock) if not m.startswith('_')]) # all public attributes from the type are included self.assertEqual(set(), type_attrs - attrs) # creates these attributes mock.a, mock.b self.assertIn('a', dir(mock)) self.assertIn('b', dir(mock)) # instance attributes mock.c = mock.d = None self.assertIn('c', dir(mock)) self.assertIn('d', dir(mock)) # magic methods mock.__iter__ = lambda s: iter([]) self.assertIn('__iter__', dir(mock)) def test_dir_from_spec(self): mock = Mock(spec=unittest.TestCase) testcase_attrs = set(dir(unittest.TestCase)) attrs = set(dir(mock)) # all attributes from the spec are included self.assertEqual(set(), testcase_attrs - attrs) # shadow a sys attribute mock.version = 3 self.assertEqual(dir(mock).count('version'), 1) def test_filter_dir(self): patcher = patch.object(mock, 'FILTER_DIR', False) patcher.start() try: attrs = set(dir(Mock())) type_attrs = set(dir(Mock)) # ALL attributes from the type are included self.assertEqual(set(), type_attrs - attrs) finally: patcher.stop() def test_dir_does_not_include_deleted_attributes(self): mock = Mock() mock.child.return_value = 1 self.assertIn('child', dir(mock)) del mock.child self.assertNotIn('child', dir(mock)) def test_configure_mock(self): mock = Mock(foo='bar') self.assertEqual(mock.foo, 'bar') mock = MagicMock(foo='bar') self.assertEqual(mock.foo, 'bar') kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33, 'foo': MagicMock()} mock = Mock(**kwargs) self.assertRaises(KeyError, mock) self.assertEqual(mock.foo.bar(), 33) self.assertIsInstance(mock.foo, MagicMock) mock = Mock() mock.configure_mock(**kwargs) self.assertRaises(KeyError, mock) self.assertEqual(mock.foo.bar(), 33) self.assertIsInstance(mock.foo, MagicMock) def assertRaisesWithMsg(self, exception, message, func, *args, **kwargs): # needed because assertRaisesRegex doesn't work easily with newlines with self.assertRaises(exception) as context: func(*args, **kwargs) msg = str(context.exception) self.assertEqual(msg, message) def test_assert_called_with_failure_message(self): mock = NonCallableMock() actual = 'not called.' expected = "mock(1, '2', 3, bar='foo')" message = 'expected call not found.\nExpected: %s\nActual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), mock.assert_called_with, 1, '2', 3, bar='foo' ) mock.foo(1, '2', 3, foo='foo') asserters = [ mock.foo.assert_called_with, mock.foo.assert_called_once_with ] for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(1, '2', 3, bar='foo')" message = 'expected call not found.\nExpected: %s\nActual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, 1, '2', 3, bar='foo' ) # just kwargs for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(bar='foo')" message = 'expected call not found.\nExpected: %s\nActual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, bar='foo' ) # just args for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo(1, 2, 3)" message = 'expected call not found.\nExpected: %s\nActual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth, 1, 2, 3 ) # empty for meth in asserters: actual = "foo(1, '2', 3, foo='foo')" expected = "foo()" message = 'expected call not found.\nExpected: %s\nActual: %s' self.assertRaisesWithMsg( AssertionError, message % (expected, actual), meth ) def test_mock_calls(self): mock = MagicMock() # need to do this because MagicMock.mock_calls used to just return # a MagicMock which also returned a MagicMock when __eq__ was called self.assertIs(mock.mock_calls == [], True) mock = MagicMock() mock() expected = [('', (), {})] self.assertEqual(mock.mock_calls, expected) mock.foo() expected.append(call.foo()) self.assertEqual(mock.mock_calls, expected) # intermediate mock_calls work too self.assertEqual(mock.foo.mock_calls, [('', (), {})]) mock = MagicMock() mock().foo(1, 2, 3, a=4, b=5) expected = [ ('', (), {}), ('().foo', (1, 2, 3), dict(a=4, b=5)) ] self.assertEqual(mock.mock_calls, expected) self.assertEqual(mock.return_value.foo.mock_calls, [('', (1, 2, 3), dict(a=4, b=5))]) self.assertEqual(mock.return_value.mock_calls, [('foo', (1, 2, 3), dict(a=4, b=5))]) mock = MagicMock() mock().foo.bar().baz() expected = [ ('', (), {}), ('().foo.bar', (), {}), ('().foo.bar().baz', (), {}) ] self.assertEqual(mock.mock_calls, expected) self.assertEqual(mock().mock_calls, call.foo.bar().baz().call_list()) for kwargs in dict(), dict(name='bar'): mock = MagicMock(**kwargs) int(mock.foo) expected = [('foo.__int__', (), {})] self.assertEqual(mock.mock_calls, expected) mock = MagicMock(**kwargs) mock.a()() expected = [('a', (), {}), ('a()', (), {})] self.assertEqual(mock.mock_calls, expected) self.assertEqual(mock.a().mock_calls, [call()]) mock = MagicMock(**kwargs) mock(1)(2)(3) self.assertEqual(mock.mock_calls, call(1)(2)(3).call_list()) self.assertEqual(mock().mock_calls, call(2)(3).call_list()) self.assertEqual(mock()().mock_calls, call(3).call_list()) mock = MagicMock(**kwargs) mock(1)(2)(3).a.b.c(4) self.assertEqual(mock.mock_calls, call(1)(2)(3).a.b.c(4).call_list()) self.assertEqual(mock().mock_calls, call(2)(3).a.b.c(4).call_list()) self.assertEqual(mock()().mock_calls, call(3).a.b.c(4).call_list()) mock = MagicMock(**kwargs) int(mock().foo.bar().baz()) last_call = ('().foo.bar().baz().__int__', (), {}) self.assertEqual(mock.mock_calls[-1], last_call) self.assertEqual(mock().mock_calls, call.foo.bar().baz().__int__().call_list()) self.assertEqual(mock().foo.bar().mock_calls, call.baz().__int__().call_list()) self.assertEqual(mock().foo.bar().baz.mock_calls, call().__int__().call_list()) def test_child_mock_call_equal(self): m = Mock() result = m() result.wibble() # parent looks like this: self.assertEqual(m.mock_calls, [call(), call().wibble()]) # but child should look like this: self.assertEqual(result.mock_calls, [call.wibble()]) def test_mock_call_not_equal_leaf(self): m = Mock() m.foo().something() self.assertNotEqual(m.mock_calls[1], call.foo().different()) self.assertEqual(m.mock_calls[0], call.foo()) def test_mock_call_not_equal_non_leaf(self): m = Mock() m.foo().bar() self.assertNotEqual(m.mock_calls[1], call.baz().bar()) self.assertNotEqual(m.mock_calls[0], call.baz()) def test_mock_call_not_equal_non_leaf_params_different(self): m = Mock() m.foo(x=1).bar() # This isn't ideal, but there's no way to fix it without breaking backwards compatibility: self.assertEqual(m.mock_calls[1], call.foo(x=2).bar()) def test_mock_call_not_equal_non_leaf_attr(self): m = Mock() m.foo.bar() self.assertNotEqual(m.mock_calls[0], call.baz.bar()) def test_mock_call_not_equal_non_leaf_call_versus_attr(self): m = Mock() m.foo.bar() self.assertNotEqual(m.mock_calls[0], call.foo().bar()) def test_mock_call_repr(self): m = Mock() m.foo().bar().baz.bob() self.assertEqual(repr(m.mock_calls[0]), 'call.foo()') self.assertEqual(repr(m.mock_calls[1]), 'call.foo().bar()') self.assertEqual(repr(m.mock_calls[2]), 'call.foo().bar().baz.bob()') def test_mock_call_repr_loop(self): m = Mock() m.foo = m repr(m.foo()) self.assertRegex(repr(m.foo()), r"") def test_mock_calls_contains(self): m = Mock() self.assertFalse([call()] in m.mock_calls) def test_subclassing(self): class Subclass(Mock): pass mock = Subclass() self.assertIsInstance(mock.foo, Subclass) self.assertIsInstance(mock(), Subclass) class Subclass(Mock): def _get_child_mock(self, **kwargs): return Mock(**kwargs) mock = Subclass() self.assertNotIsInstance(mock.foo, Subclass) self.assertNotIsInstance(mock(), Subclass) def test_arg_lists(self): mocks = [ Mock(), MagicMock(), NonCallableMock(), NonCallableMagicMock() ] def assert_attrs(mock): names = 'call_args_list', 'method_calls', 'mock_calls' for name in names: attr = getattr(mock, name) self.assertIsInstance(attr, _CallList) self.assertIsInstance(attr, list) self.assertEqual(attr, []) for mock in mocks: assert_attrs(mock) if callable(mock): mock() mock(1, 2) mock(a=3) mock.reset_mock() assert_attrs(mock) mock.foo() mock.foo.bar(1, a=3) mock.foo(1).bar().baz(3) mock.reset_mock() assert_attrs(mock) def test_call_args_two_tuple(self): mock = Mock() mock(1, a=3) mock(2, b=4) self.assertEqual(len(mock.call_args), 2) self.assertEqual(mock.call_args.args, (2,)) self.assertEqual(mock.call_args.kwargs, dict(b=4)) expected_list = [((1,), dict(a=3)), ((2,), dict(b=4))] for expected, call_args in zip(expected_list, mock.call_args_list): self.assertEqual(len(call_args), 2) self.assertEqual(expected[0], call_args[0]) self.assertEqual(expected[1], call_args[1]) def test_side_effect_iterator(self): mock = Mock(side_effect=iter([1, 2, 3])) self.assertEqual([mock(), mock(), mock()], [1, 2, 3]) self.assertRaises(StopIteration, mock) mock = MagicMock(side_effect=['a', 'b', 'c']) self.assertEqual([mock(), mock(), mock()], ['a', 'b', 'c']) self.assertRaises(StopIteration, mock) mock = Mock(side_effect='ghi') self.assertEqual([mock(), mock(), mock()], ['g', 'h', 'i']) self.assertRaises(StopIteration, mock) class Foo(object): pass mock = MagicMock(side_effect=Foo) self.assertIsInstance(mock(), Foo) mock = Mock(side_effect=Iter()) self.assertEqual([mock(), mock(), mock(), mock()], ['this', 'is', 'an', 'iter']) self.assertRaises(StopIteration, mock) def test_side_effect_iterator_exceptions(self): for Klass in Mock, MagicMock: iterable = (ValueError, 3, KeyError, 6) m = Klass(side_effect=iterable) self.assertRaises(ValueError, m) self.assertEqual(m(), 3) self.assertRaises(KeyError, m) self.assertEqual(m(), 6) def test_side_effect_setting_iterator(self): mock = Mock() mock.side_effect = iter([1, 2, 3]) self.assertEqual([mock(), mock(), mock()], [1, 2, 3]) self.assertRaises(StopIteration, mock) side_effect = mock.side_effect self.assertIsInstance(side_effect, type(iter([]))) mock.side_effect = ['a', 'b', 'c'] self.assertEqual([mock(), mock(), mock()], ['a', 'b', 'c']) self.assertRaises(StopIteration, mock) side_effect = mock.side_effect self.assertIsInstance(side_effect, type(iter([]))) this_iter = Iter() mock.side_effect = this_iter self.assertEqual([mock(), mock(), mock(), mock()], ['this', 'is', 'an', 'iter']) self.assertRaises(StopIteration, mock) self.assertIs(mock.side_effect, this_iter) def test_side_effect_iterator_default(self): mock = Mock(return_value=2) mock.side_effect = iter([1, DEFAULT]) self.assertEqual([mock(), mock()], [1, 2]) def test_assert_has_calls_any_order(self): mock = Mock() mock(1, 2) mock(a=3) mock(3, 4) mock(b=6) mock(b=6) kalls = [ call(1, 2), ({'a': 3},), ((3, 4),), ((), {'a': 3}), ('', (1, 2)), ('', {'a': 3}), ('', (1, 2), {}), ('', (), {'a': 3}) ] for kall in kalls: mock.assert_has_calls([kall], any_order=True) for kall in call(1, '2'), call(b=3), call(), 3, None, 'foo': self.assertRaises( AssertionError, mock.assert_has_calls, [kall], any_order=True ) kall_lists = [ [call(1, 2), call(b=6)], [call(3, 4), call(1, 2)], [call(b=6), call(b=6)], ] for kall_list in kall_lists: mock.assert_has_calls(kall_list, any_order=True) kall_lists = [ [call(b=6), call(b=6), call(b=6)], [call(1, 2), call(1, 2)], [call(3, 4), call(1, 2), call(5, 7)], [call(b=6), call(3, 4), call(b=6), call(1, 2), call(b=6)], ] for kall_list in kall_lists: self.assertRaises( AssertionError, mock.assert_has_calls, kall_list, any_order=True ) def test_assert_has_calls(self): kalls1 = [ call(1, 2), ({'a': 3},), ((3, 4),), call(b=6), ('', (1,), {'b': 6}), ] kalls2 = [call.foo(), call.bar(1)] kalls2.extend(call.spam().baz(a=3).call_list()) kalls2.extend(call.bam(set(), foo={}).fish([1]).call_list()) mocks = [] for mock in Mock(), MagicMock(): mock(1, 2) mock(a=3) mock(3, 4) mock(b=6) mock(1, b=6) mocks.append((mock, kalls1)) mock = Mock() mock.foo() mock.bar(1) mock.spam().baz(a=3) mock.bam(set(), foo={}).fish([1]) mocks.append((mock, kalls2)) for mock, kalls in mocks: for i in range(len(kalls)): for step in 1, 2, 3: these = kalls[i:i+step] mock.assert_has_calls(these) if len(these) > 1: self.assertRaises( AssertionError, mock.assert_has_calls, list(reversed(these)) ) def test_assert_has_calls_nested_spec(self): class Something: def __init__(self): pass def meth(self, a, b, c, d=None): pass class Foo: def __init__(self, a): pass def meth1(self, a, b): pass mock_class = create_autospec(Something) for m in [mock_class, mock_class()]: m.meth(1, 2, 3, d=1) m.assert_has_calls([call.meth(1, 2, 3, d=1)]) m.assert_has_calls([call.meth(1, 2, 3, 1)]) mock_class.reset_mock() for m in [mock_class, mock_class()]: self.assertRaises(AssertionError, m.assert_has_calls, [call.Foo()]) m.Foo(1).meth1(1, 2) m.assert_has_calls([call.Foo(1), call.Foo(1).meth1(1, 2)]) m.Foo.assert_has_calls([call(1), call().meth1(1, 2)]) mock_class.reset_mock() invalid_calls = [call.meth(1), call.non_existent(1), call.Foo().non_existent(1), call.Foo().meth(1, 2, 3, 4)] for kall in invalid_calls: self.assertRaises(AssertionError, mock_class.assert_has_calls, [kall] ) def test_assert_has_calls_nested_without_spec(self): m = MagicMock() m().foo().bar().baz() m.one().two().three() calls = call.one().two().three().call_list() m.assert_has_calls(calls) def test_assert_has_calls_with_function_spec(self): def f(a, b, c, d=None): pass mock = Mock(spec=f) mock(1, b=2, c=3) mock(4, 5, c=6, d=7) mock(10, 11, c=12) calls = [ ('', (1, 2, 3), {}), ('', (4, 5, 6), {'d': 7}), ((10, 11, 12), {}), ] mock.assert_has_calls(calls) mock.assert_has_calls(calls, any_order=True) mock.assert_has_calls(calls[1:]) mock.assert_has_calls(calls[1:], any_order=True) mock.assert_has_calls(calls[:-1]) mock.assert_has_calls(calls[:-1], any_order=True) # Reversed order calls = list(reversed(calls)) with self.assertRaises(AssertionError): mock.assert_has_calls(calls) mock.assert_has_calls(calls, any_order=True) with self.assertRaises(AssertionError): mock.assert_has_calls(calls[1:]) mock.assert_has_calls(calls[1:], any_order=True) with self.assertRaises(AssertionError): mock.assert_has_calls(calls[:-1]) mock.assert_has_calls(calls[:-1], any_order=True) def test_assert_has_calls_not_matching_spec_error(self): def f(x=None): pass mock = Mock(spec=f) mock(1) with self.assertRaisesRegex( AssertionError, '^{}$'.format( re.escape('Calls not found.\n' 'Expected: [call()]\n' 'Actual: [call(1)]'))) as cm: mock.assert_has_calls([call()]) self.assertIsNone(cm.exception.__cause__) with self.assertRaisesRegex( AssertionError, '^{}$'.format( re.escape( 'Error processing expected calls.\n' "Errors: [None, TypeError('too many positional arguments')]\n" "Expected: [call(), call(1, 2)]\n" 'Actual: [call(1)]').replace( "arguments\\'", "arguments\\',?" ))) as cm: mock.assert_has_calls([call(), call(1, 2)]) self.assertIsInstance(cm.exception.__cause__, TypeError) def test_assert_any_call(self): mock = Mock() mock(1, 2) mock(a=3) mock(1, b=6) mock.assert_any_call(1, 2) mock.assert_any_call(a=3) mock.assert_any_call(1, b=6) self.assertRaises( AssertionError, mock.assert_any_call ) self.assertRaises( AssertionError, mock.assert_any_call, 1, 3 ) self.assertRaises( AssertionError, mock.assert_any_call, a=4 ) def test_assert_any_call_with_function_spec(self): def f(a, b, c, d=None): pass mock = Mock(spec=f) mock(1, b=2, c=3) mock(4, 5, c=6, d=7) mock.assert_any_call(1, 2, 3) mock.assert_any_call(a=1, b=2, c=3) mock.assert_any_call(4, 5, 6, 7) mock.assert_any_call(a=4, b=5, c=6, d=7) self.assertRaises(AssertionError, mock.assert_any_call, 1, b=3, c=2) # Expected call doesn't match the spec's signature with self.assertRaises(AssertionError) as cm: mock.assert_any_call(e=8) self.assertIsInstance(cm.exception.__cause__, TypeError) def test_mock_calls_create_autospec(self): def f(a, b): pass obj = Iter() obj.f = f funcs = [ create_autospec(f), create_autospec(obj).f ] for func in funcs: func(1, 2) func(3, 4) self.assertEqual( func.mock_calls, [call(1, 2), call(3, 4)] ) #Issue21222 def test_create_autospec_with_name(self): m = mock.create_autospec(object(), name='sweet_func') self.assertIn('sweet_func', repr(m)) #Issue23078 def test_create_autospec_classmethod_and_staticmethod(self): class TestClass: @classmethod def class_method(cls): pass @staticmethod def static_method(): pass for method in ('class_method', 'static_method'): with self.subTest(method=method): mock_method = mock.create_autospec(getattr(TestClass, method)) mock_method() mock_method.assert_called_once_with() self.assertRaises(TypeError, mock_method, 'extra_arg') #Issue21238 def test_mock_unsafe(self): m = Mock() msg = "Attributes cannot start with 'assert' or its misspellings" with self.assertRaisesRegex(AttributeError, msg): m.assert_foo_call() with self.assertRaisesRegex(AttributeError, msg): m.assret_foo_call() with self.assertRaisesRegex(AttributeError, msg): m.asert_foo_call() with self.assertRaisesRegex(AttributeError, msg): m.aseert_foo_call() with self.assertRaisesRegex(AttributeError, msg): m.assrt_foo_call() m = Mock(unsafe=True) m.assert_foo_call() m.assret_foo_call() m.asert_foo_call() m.aseert_foo_call() m.assrt_foo_call() #Issue21262 def test_assert_not_called(self): m = Mock() m.hello.assert_not_called() m.hello() with self.assertRaises(AssertionError): m.hello.assert_not_called() def test_assert_not_called_message(self): m = Mock() m(1, 2) self.assertRaisesRegex(AssertionError, re.escape("Calls: [call(1, 2)]"), m.assert_not_called) def test_assert_called(self): m = Mock() with self.assertRaises(AssertionError): m.hello.assert_called() m.hello() m.hello.assert_called() m.hello() m.hello.assert_called() def test_assert_called_once(self): m = Mock() with self.assertRaises(AssertionError): m.hello.assert_called_once() m.hello() m.hello.assert_called_once() m.hello() with self.assertRaises(AssertionError): m.hello.assert_called_once() def test_assert_called_once_message(self): m = Mock() m(1, 2) m(3) self.assertRaisesRegex(AssertionError, re.escape("Calls: [call(1, 2), call(3)]"), m.assert_called_once) def test_assert_called_once_message_not_called(self): m = Mock() with self.assertRaises(AssertionError) as e: m.assert_called_once() self.assertNotIn("Calls:", str(e.exception)) #Issue37212 printout of keyword args now preserves the original order def test_ordered_call_signature(self): m = Mock() m.hello(name='hello', daddy='hero') text = "call(name='hello', daddy='hero')" self.assertEqual(repr(m.hello.call_args), text) #Issue21270 overrides tuple methods for mock.call objects def test_override_tuple_methods(self): c = call.count() i = call.index(132,'hello') m = Mock() m.count() m.index(132,"hello") self.assertEqual(m.method_calls[0], c) self.assertEqual(m.method_calls[1], i) def test_reset_return_sideeffect(self): m = Mock(return_value=10, side_effect=[2,3]) m.reset_mock(return_value=True, side_effect=True) self.assertIsInstance(m.return_value, Mock) self.assertEqual(m.side_effect, None) def test_reset_return(self): m = Mock(return_value=10, side_effect=[2,3]) m.reset_mock(return_value=True) self.assertIsInstance(m.return_value, Mock) self.assertNotEqual(m.side_effect, None) def test_reset_sideeffect(self): m = Mock(return_value=10, side_effect=[2, 3]) m.reset_mock(side_effect=True) self.assertEqual(m.return_value, 10) self.assertEqual(m.side_effect, None) def test_reset_return_with_children(self): m = MagicMock(f=MagicMock(return_value=1)) self.assertEqual(m.f(), 1) m.reset_mock(return_value=True) self.assertNotEqual(m.f(), 1) def test_reset_return_with_children_side_effect(self): m = MagicMock(f=MagicMock(side_effect=[2, 3])) self.assertNotEqual(m.f.side_effect, None) m.reset_mock(side_effect=True) self.assertEqual(m.f.side_effect, None) def test_mock_add_spec(self): class _One(object): one = 1 class _Two(object): two = 2 class Anything(object): one = two = three = 'four' klasses = [ Mock, MagicMock, NonCallableMock, NonCallableMagicMock ] for Klass in list(klasses): klasses.append(lambda K=Klass: K(spec=Anything)) klasses.append(lambda K=Klass: K(spec_set=Anything)) for Klass in klasses: for kwargs in dict(), dict(spec_set=True): mock = Klass() #no error mock.one, mock.two, mock.three for One, Two in [(_One, _Two), (['one'], ['two'])]: for kwargs in dict(), dict(spec_set=True): mock.mock_add_spec(One, **kwargs) mock.one self.assertRaises( AttributeError, getattr, mock, 'two' ) self.assertRaises( AttributeError, getattr, mock, 'three' ) if 'spec_set' in kwargs: self.assertRaises( AttributeError, setattr, mock, 'three', None ) mock.mock_add_spec(Two, **kwargs) self.assertRaises( AttributeError, getattr, mock, 'one' ) mock.two self.assertRaises( AttributeError, getattr, mock, 'three' ) if 'spec_set' in kwargs: self.assertRaises( AttributeError, setattr, mock, 'three', None ) # note that creating a mock, setting an instance attribute, and # *then* setting a spec doesn't work. Not the intended use case def test_mock_add_spec_magic_methods(self): for Klass in MagicMock, NonCallableMagicMock: mock = Klass() int(mock) mock.mock_add_spec(object) self.assertRaises(TypeError, int, mock) mock = Klass() mock['foo'] mock.__int__.return_value =4 mock.mock_add_spec(int) self.assertEqual(int(mock), 4) self.assertRaises(TypeError, lambda: mock['foo']) def test_adding_child_mock(self): for Klass in (NonCallableMock, Mock, MagicMock, NonCallableMagicMock, AsyncMock): mock = Klass() mock.foo = Mock() mock.foo() self.assertEqual(mock.method_calls, [call.foo()]) self.assertEqual(mock.mock_calls, [call.foo()]) mock = Klass() mock.bar = Mock(name='name') mock.bar() self.assertEqual(mock.method_calls, []) self.assertEqual(mock.mock_calls, []) # mock with an existing _new_parent but no name mock = Klass() mock.baz = MagicMock()() mock.baz() self.assertEqual(mock.method_calls, []) self.assertEqual(mock.mock_calls, []) def test_adding_return_value_mock(self): for Klass in Mock, MagicMock: mock = Klass() mock.return_value = MagicMock() mock()() self.assertEqual(mock.mock_calls, [call(), call()()]) def test_manager_mock(self): class Foo(object): one = 'one' two = 'two' manager = Mock() p1 = patch.object(Foo, 'one') p2 = patch.object(Foo, 'two') mock_one = p1.start() self.addCleanup(p1.stop) mock_two = p2.start() self.addCleanup(p2.stop) manager.attach_mock(mock_one, 'one') manager.attach_mock(mock_two, 'two') Foo.two() Foo.one() self.assertEqual(manager.mock_calls, [call.two(), call.one()]) def test_magic_methods_mock_calls(self): for Klass in Mock, MagicMock: m = Klass() m.__int__ = Mock(return_value=3) m.__float__ = MagicMock(return_value=3.0) int(m) float(m) self.assertEqual(m.mock_calls, [call.__int__(), call.__float__()]) self.assertEqual(m.method_calls, []) def test_mock_open_reuse_issue_21750(self): mocked_open = mock.mock_open(read_data='data') f1 = mocked_open('a-name') f1_data = f1.read() f2 = mocked_open('another-name') f2_data = f2.read() self.assertEqual(f1_data, f2_data) def test_mock_open_dunder_iter_issue(self): # Test dunder_iter method generates the expected result and # consumes the iterator. mocked_open = mock.mock_open(read_data='Remarkable\nNorwegian Blue') f1 = mocked_open('a-name') lines = [line for line in f1] self.assertEqual(lines[0], 'Remarkable\n') self.assertEqual(lines[1], 'Norwegian Blue') self.assertEqual(list(f1), []) def test_mock_open_using_next(self): mocked_open = mock.mock_open(read_data='1st line\n2nd line\n3rd line') f1 = mocked_open('a-name') line1 = next(f1) line2 = f1.__next__() lines = [line for line in f1] self.assertEqual(line1, '1st line\n') self.assertEqual(line2, '2nd line\n') self.assertEqual(lines[0], '3rd line') self.assertEqual(list(f1), []) with self.assertRaises(StopIteration): next(f1) def test_mock_open_next_with_readline_with_return_value(self): mopen = mock.mock_open(read_data='foo\nbarn') mopen.return_value.readline.return_value = 'abc' self.assertEqual('abc', next(mopen())) def test_mock_open_write(self): # Test exception in file writing write() mock_namedtemp = mock.mock_open(mock.MagicMock(name='JLV')) with mock.patch('tempfile.NamedTemporaryFile', mock_namedtemp): mock_filehandle = mock_namedtemp.return_value mock_write = mock_filehandle.write mock_write.side_effect = OSError('Test 2 Error') def attempt(): tempfile.NamedTemporaryFile().write('asd') self.assertRaises(OSError, attempt) def test_mock_open_alter_readline(self): mopen = mock.mock_open(read_data='foo\nbarn') mopen.return_value.readline.side_effect = lambda *args:'abc' first = mopen().readline() second = mopen().readline() self.assertEqual('abc', first) self.assertEqual('abc', second) def test_mock_open_after_eof(self): # read, readline and readlines should work after end of file. _open = mock.mock_open(read_data='foo') h = _open('bar') h.read() self.assertEqual('', h.read()) self.assertEqual('', h.read()) self.assertEqual('', h.readline()) self.assertEqual('', h.readline()) self.assertEqual([], h.readlines()) self.assertEqual([], h.readlines()) def test_mock_parents(self): for Klass in Mock, MagicMock: m = Klass() original_repr = repr(m) m.return_value = m self.assertIs(m(), m) self.assertEqual(repr(m), original_repr) m.reset_mock() self.assertIs(m(), m) self.assertEqual(repr(m), original_repr) m = Klass() m.b = m.a self.assertIn("name='mock.a'", repr(m.b)) self.assertIn("name='mock.a'", repr(m.a)) m.reset_mock() self.assertIn("name='mock.a'", repr(m.b)) self.assertIn("name='mock.a'", repr(m.a)) m = Klass() original_repr = repr(m) m.a = m() m.a.return_value = m self.assertEqual(repr(m), original_repr) self.assertEqual(repr(m.a()), original_repr) def test_attach_mock(self): classes = Mock, MagicMock, NonCallableMagicMock, NonCallableMock for Klass in classes: for Klass2 in classes: m = Klass() m2 = Klass2(name='foo') m.attach_mock(m2, 'bar') self.assertIs(m.bar, m2) self.assertIn("name='mock.bar'", repr(m2)) m.bar.baz(1) self.assertEqual(m.mock_calls, [call.bar.baz(1)]) self.assertEqual(m.method_calls, [call.bar.baz(1)]) def test_attach_mock_return_value(self): classes = Mock, MagicMock, NonCallableMagicMock, NonCallableMock for Klass in Mock, MagicMock: for Klass2 in classes: m = Klass() m2 = Klass2(name='foo') m.attach_mock(m2, 'return_value') self.assertIs(m(), m2) self.assertIn("name='mock()'", repr(m2)) m2.foo() self.assertEqual(m.mock_calls, call().foo().call_list()) def test_attach_mock_patch_autospec(self): parent = Mock() with mock.patch(f'{__name__}.something', autospec=True) as mock_func: self.assertEqual(mock_func.mock._extract_mock_name(), 'something') parent.attach_mock(mock_func, 'child') parent.child(1) something(2) mock_func(3) parent_calls = [call.child(1), call.child(2), call.child(3)] child_calls = [call(1), call(2), call(3)] self.assertEqual(parent.mock_calls, parent_calls) self.assertEqual(parent.child.mock_calls, child_calls) self.assertEqual(something.mock_calls, child_calls) self.assertEqual(mock_func.mock_calls, child_calls) self.assertIn('mock.child', repr(parent.child.mock)) self.assertEqual(mock_func.mock._extract_mock_name(), 'mock.child') def test_attach_mock_patch_autospec_signature(self): with mock.patch(f'{__name__}.Something.meth', autospec=True) as mocked: manager = Mock() manager.attach_mock(mocked, 'attach_meth') obj = Something() obj.meth(1, 2, 3, d=4) manager.assert_has_calls([call.attach_meth(mock.ANY, 1, 2, 3, d=4)]) obj.meth.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)]) mocked.assert_has_calls([call(mock.ANY, 1, 2, 3, d=4)]) with mock.patch(f'{__name__}.something', autospec=True) as mocked: manager = Mock() manager.attach_mock(mocked, 'attach_func') something(1) manager.assert_has_calls([call.attach_func(1)]) something.assert_has_calls([call(1)]) mocked.assert_has_calls([call(1)]) with mock.patch(f'{__name__}.Something', autospec=True) as mocked: manager = Mock() manager.attach_mock(mocked, 'attach_obj') obj = Something() obj.meth(1, 2, 3, d=4) manager.assert_has_calls([call.attach_obj(), call.attach_obj().meth(1, 2, 3, d=4)]) obj.meth.assert_has_calls([call(1, 2, 3, d=4)]) mocked.assert_has_calls([call(), call().meth(1, 2, 3, d=4)]) def test_attribute_deletion(self): for mock in (Mock(), MagicMock(), NonCallableMagicMock(), NonCallableMock()): self.assertTrue(hasattr(mock, 'm')) del mock.m self.assertFalse(hasattr(mock, 'm')) del mock.f self.assertFalse(hasattr(mock, 'f')) self.assertRaises(AttributeError, getattr, mock, 'f') def test_mock_does_not_raise_on_repeated_attribute_deletion(self): # bpo-20239: Assigning and deleting twice an attribute raises. for mock in (Mock(), MagicMock(), NonCallableMagicMock(), NonCallableMock()): mock.foo = 3 self.assertTrue(hasattr(mock, 'foo')) self.assertEqual(mock.foo, 3) del mock.foo self.assertFalse(hasattr(mock, 'foo')) mock.foo = 4 self.assertTrue(hasattr(mock, 'foo')) self.assertEqual(mock.foo, 4) del mock.foo self.assertFalse(hasattr(mock, 'foo')) def test_mock_raises_when_deleting_nonexistent_attribute(self): for mock in (Mock(), MagicMock(), NonCallableMagicMock(), NonCallableMock()): del mock.foo with self.assertRaises(AttributeError): del mock.foo def test_reset_mock_does_not_raise_on_attr_deletion(self): # bpo-31177: reset_mock should not raise AttributeError when attributes # were deleted in a mock instance mock = Mock() mock.child = True del mock.child mock.reset_mock() self.assertFalse(hasattr(mock, 'child')) def test_class_assignable(self): for mock in Mock(), MagicMock(): self.assertNotIsInstance(mock, int) mock.__class__ = int self.assertIsInstance(mock, int) mock.foo def test_name_attribute_of_call(self): # bpo-35357: _Call should not disclose any attributes whose names # may clash with popular ones (such as ".name") self.assertIsNotNone(call.name) self.assertEqual(type(call.name), _Call) self.assertEqual(type(call.name().name), _Call) def test_parent_attribute_of_call(self): # bpo-35357: _Call should not disclose any attributes whose names # may clash with popular ones (such as ".parent") self.assertIsNotNone(call.parent) self.assertEqual(type(call.parent), _Call) self.assertEqual(type(call.parent().parent), _Call) def test_parent_propagation_with_create_autospec(self): def foo(a, b): pass mock = Mock() mock.child = create_autospec(foo) mock.child(1, 2) self.assertRaises(TypeError, mock.child, 1) self.assertEqual(mock.mock_calls, [call.child(1, 2)]) self.assertIn('mock.child', repr(mock.child.mock)) def test_parent_propagation_with_autospec_attach_mock(self): def foo(a, b): pass parent = Mock() parent.attach_mock(create_autospec(foo, name='bar'), 'child') parent.child(1, 2) self.assertRaises(TypeError, parent.child, 1) self.assertEqual(parent.child.mock_calls, [call.child(1, 2)]) self.assertIn('mock.child', repr(parent.child.mock)) def test_isinstance_under_settrace(self): # bpo-36593 : __class__ is not set for a class that has __class__ # property defined when it's used with sys.settrace(trace) set. # Delete the module to force reimport with tracing function set # restore the old reference later since there are other tests that are # dependent on unittest.mock.patch. In testpatch.PatchTest # test_patch_dict_test_prefix and test_patch_test_prefix not restoring # causes the objects patched to go out of sync old_patch = unittest.mock.patch # Directly using __setattr__ on unittest.mock causes current imported # reference to be updated. Use a lambda so that during cleanup the # re-imported new reference is updated. self.addCleanup(lambda patch: setattr(unittest.mock, 'patch', patch), old_patch) with patch.dict('sys.modules'): del sys.modules['unittest.mock'] # This trace will stop coverage being measured ;-) def trace(frame, event, arg): # pragma: no cover return trace self.addCleanup(sys.settrace, sys.gettrace()) sys.settrace(trace) from unittest.mock import ( Mock, MagicMock, NonCallableMock, NonCallableMagicMock ) mocks = [ Mock, MagicMock, NonCallableMock, NonCallableMagicMock, AsyncMock ] for mock in mocks: obj = mock(spec=Something) self.assertIsInstance(obj, Something) def test_bool_not_called_when_passing_spec_arg(self): class Something: def __init__(self): self.obj_with_bool_func = unittest.mock.MagicMock() obj = Something() with unittest.mock.patch.object(obj, 'obj_with_bool_func', autospec=True): pass self.assertEqual(obj.obj_with_bool_func.__bool__.call_count, 0) if __name__ == '__main__': unittest.main() mock-4.0.3/mock/tests/testpatch.py000066400000000000000000001626771376434722300171510ustar00rootroot00000000000000# Copyright (C) 2007-2012 Michael Foord & the mock team # E-mail: fuzzyman AT voidspace DOT org DOT uk # http://www.voidspace.org.uk/python/mock/ import os import sys from collections import OrderedDict import unittest from mock.tests import support from mock.tests.support import SomeClass, is_instance from .support import uncache from mock import ( NonCallableMock, sentinel, MagicMock, Mock, NonCallableMagicMock, patch, DEFAULT, call ) from mock.mock import CallableMixin, _patch, _get_target builtin_string = 'builtins' PTModule = sys.modules[__name__] MODNAME = '%s.PTModule' % __name__ def _get_proxy(obj, get_only=True): class Proxy(object): def __getattr__(self, name): return getattr(obj, name) if not get_only: def __setattr__(self, name, value): setattr(obj, name, value) def __delattr__(self, name): delattr(obj, name) Proxy.__setattr__ = __setattr__ Proxy.__delattr__ = __delattr__ return Proxy() # for use in the test something = sentinel.Something something_else = sentinel.SomethingElse class Foo(object): def __init__(self, a): pass def f(self, a): pass def g(self): pass foo = 'bar' @staticmethod def static_method(): pass @classmethod def class_method(cls): pass class Bar(object): def a(self): pass foo_name = '%s.Foo' % __name__ def function(a, b=Foo): pass class Container(object): def __init__(self): self.values = {} def __getitem__(self, name): return self.values[name] def __setitem__(self, name, value): self.values[name] = value def __delitem__(self, name): del self.values[name] def __iter__(self): return iter(self.values) class PatchTest(unittest.TestCase): def assertNotCallable(self, obj, magic=True): MockClass = NonCallableMagicMock if not magic: MockClass = NonCallableMock self.assertRaises(TypeError, obj) self.assertTrue(is_instance(obj, MockClass)) self.assertFalse(is_instance(obj, CallableMixin)) def test_single_patchobject(self): class Something(object): attribute = sentinel.Original @patch.object(Something, 'attribute', sentinel.Patched) def test(): self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") test() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") def test_patchobject_with_string_as_target(self): msg = "'Something' must be the actual object to be patched, not a str" with self.assertRaisesRegex(TypeError, msg): patch.object('Something', 'do_something') def test_patchobject_with_none(self): class Something(object): attribute = sentinel.Original @patch.object(Something, 'attribute', None) def test(): self.assertIsNone(Something.attribute, "unpatched") test() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") def test_multiple_patchobject(self): class Something(object): attribute = sentinel.Original next_attribute = sentinel.Original2 @patch.object(Something, 'attribute', sentinel.Patched) @patch.object(Something, 'next_attribute', sentinel.Patched2) def test(): self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") self.assertEqual(Something.next_attribute, sentinel.Patched2, "unpatched") test() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") self.assertEqual(Something.next_attribute, sentinel.Original2, "patch not restored") def test_object_lookup_is_quite_lazy(self): global something original = something @patch('%s.something' % __name__, sentinel.Something2) def test(): pass try: something = sentinel.replacement_value test() self.assertEqual(something, sentinel.replacement_value) finally: something = original def test_patch(self): @patch('%s.something' % __name__, sentinel.Something2) def test(): self.assertEqual(PTModule.something, sentinel.Something2, "unpatched") test() self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") @patch('%s.something' % __name__, sentinel.Something2) @patch('%s.something_else' % __name__, sentinel.SomethingElse) def test(): self.assertEqual(PTModule.something, sentinel.Something2, "unpatched") self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "unpatched") self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored") # Test the patching and restoring works a second time test() self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") self.assertEqual(PTModule.something_else, sentinel.SomethingElse, "patch not restored") mock = Mock() mock.return_value = sentinel.Handle @patch('%s.open' % builtin_string, mock) def test(): self.assertEqual(open('filename', 'r'), sentinel.Handle, "open not patched") test() test() self.assertNotEqual(open, mock, "patch not restored") def test_patch_class_attribute(self): @patch('%s.SomeClass.class_attribute' % __name__, sentinel.ClassAttribute) def test(): self.assertEqual(PTModule.SomeClass.class_attribute, sentinel.ClassAttribute, "unpatched") test() self.assertIsNone(PTModule.SomeClass.class_attribute, "patch not restored") def test_patchobject_with_default_mock(self): class Test(object): something = sentinel.Original something2 = sentinel.Original2 @patch.object(Test, 'something') def test(mock): self.assertEqual(mock, Test.something, "Mock not passed into test function") self.assertIsInstance(mock, MagicMock, "patch with two arguments did not create a mock") test() @patch.object(Test, 'something') @patch.object(Test, 'something2') def test(this1, this2, mock1, mock2): self.assertEqual(this1, sentinel.this1, "Patched function didn't receive initial argument") self.assertEqual(this2, sentinel.this2, "Patched function didn't receive second argument") self.assertEqual(mock1, Test.something2, "Mock not passed into test function") self.assertEqual(mock2, Test.something, "Second Mock not passed into test function") self.assertIsInstance(mock2, MagicMock, "patch with two arguments did not create a mock") self.assertIsInstance(mock2, MagicMock, "patch with two arguments did not create a mock") # A hack to test that new mocks are passed the second time self.assertNotEqual(outerMock1, mock1, "unexpected value for mock1") self.assertNotEqual(outerMock2, mock2, "unexpected value for mock1") return mock1, mock2 outerMock1 = outerMock2 = None outerMock1, outerMock2 = test(sentinel.this1, sentinel.this2) # Test that executing a second time creates new mocks test(sentinel.this1, sentinel.this2) def test_patch_with_spec(self): @patch('%s.SomeClass' % __name__, spec=SomeClass) def test(MockSomeClass): self.assertEqual(SomeClass, MockSomeClass) self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) test() def test_patchobject_with_spec(self): @patch.object(SomeClass, 'class_attribute', spec=SomeClass) def test(MockAttribute): self.assertEqual(SomeClass.class_attribute, MockAttribute) self.assertTrue(is_instance(SomeClass.class_attribute.wibble, MagicMock)) self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble) test() def test_patch_with_spec_as_list(self): @patch('%s.SomeClass' % __name__, spec=['wibble']) def test(MockSomeClass): self.assertEqual(SomeClass, MockSomeClass) self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) test() def test_patchobject_with_spec_as_list(self): @patch.object(SomeClass, 'class_attribute', spec=['wibble']) def test(MockAttribute): self.assertEqual(SomeClass.class_attribute, MockAttribute) self.assertTrue(is_instance(SomeClass.class_attribute.wibble, MagicMock)) self.assertRaises(AttributeError, lambda: SomeClass.class_attribute.not_wibble) test() def test_nested_patch_with_spec_as_list(self): # regression test for nested decorators @patch('%s.open' % builtin_string) @patch('%s.SomeClass' % __name__, spec=['wibble']) def test(MockSomeClass, MockOpen): self.assertEqual(SomeClass, MockSomeClass) self.assertTrue(is_instance(SomeClass.wibble, MagicMock)) self.assertRaises(AttributeError, lambda: SomeClass.not_wibble) test() def test_patch_with_spec_as_boolean(self): @patch('%s.SomeClass' % __name__, spec=True) def test(MockSomeClass): self.assertEqual(SomeClass, MockSomeClass) # Should not raise attribute error MockSomeClass.wibble self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) test() def test_patch_object_with_spec_as_boolean(self): @patch.object(PTModule, 'SomeClass', spec=True) def test(MockSomeClass): self.assertEqual(SomeClass, MockSomeClass) # Should not raise attribute error MockSomeClass.wibble self.assertRaises(AttributeError, lambda: MockSomeClass.not_wibble) test() def test_patch_class_acts_with_spec_is_inherited(self): @patch('%s.SomeClass' % __name__, spec=True) def test(MockSomeClass): self.assertTrue(is_instance(MockSomeClass, MagicMock)) instance = MockSomeClass() self.assertNotCallable(instance) # Should not raise attribute error instance.wibble self.assertRaises(AttributeError, lambda: instance.not_wibble) test() def test_patch_with_create_mocks_non_existent_attributes(self): @patch('%s.frooble' % builtin_string, sentinel.Frooble, create=True) def test(): self.assertEqual(frooble, sentinel.Frooble) test() self.assertRaises(NameError, lambda: frooble) def test_patchobject_with_create_mocks_non_existent_attributes(self): @patch.object(SomeClass, 'frooble', sentinel.Frooble, create=True) def test(): self.assertEqual(SomeClass.frooble, sentinel.Frooble) test() self.assertFalse(hasattr(SomeClass, 'frooble')) def test_patch_wont_create_by_default(self): with self.assertRaises(AttributeError): @patch('%s.frooble' % builtin_string, sentinel.Frooble) def test(): pass test() self.assertRaises(NameError, lambda: frooble) def test_patchobject_wont_create_by_default(self): with self.assertRaises(AttributeError): @patch.object(SomeClass, 'ord', sentinel.Frooble) def test(): pass test() self.assertFalse(hasattr(SomeClass, 'ord')) def test_patch_builtins_without_create(self): @patch(__name__+'.ord') def test_ord(mock_ord): mock_ord.return_value = 101 return ord('c') @patch(__name__+'.open') def test_open(mock_open): m = mock_open.return_value m.read.return_value = 'abcd' fobj = open('doesnotexists.txt') data = fobj.read() fobj.close() return data self.assertEqual(test_ord(), 101) self.assertEqual(test_open(), 'abcd') def test_patch_with_static_methods(self): class Foo(object): @staticmethod def woot(): return sentinel.Static @patch.object(Foo, 'woot', staticmethod(lambda: sentinel.Patched)) def anonymous(): self.assertEqual(Foo.woot(), sentinel.Patched) anonymous() self.assertEqual(Foo.woot(), sentinel.Static) def test_patch_local(self): foo = sentinel.Foo @patch.object(sentinel, 'Foo', 'Foo') def anonymous(): self.assertEqual(sentinel.Foo, 'Foo') anonymous() self.assertEqual(sentinel.Foo, foo) def test_patch_slots(self): class Foo(object): __slots__ = ('Foo',) foo = Foo() foo.Foo = sentinel.Foo @patch.object(foo, 'Foo', 'Foo') def anonymous(): self.assertEqual(foo.Foo, 'Foo') anonymous() self.assertEqual(foo.Foo, sentinel.Foo) def test_patchobject_class_decorator(self): class Something(object): attribute = sentinel.Original class Foo(object): def test_method(other_self): self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") def not_test_method(other_self): self.assertEqual(Something.attribute, sentinel.Original, "non-test method patched") Foo = patch.object(Something, 'attribute', sentinel.Patched)(Foo) f = Foo() f.test_method() f.not_test_method() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") def test_patch_class_decorator(self): class Something(object): attribute = sentinel.Original class Foo(object): test_class_attr = 'whatever' def test_method(other_self, mock_something): self.assertEqual(PTModule.something, mock_something, "unpatched") def not_test_method(other_self): self.assertEqual(PTModule.something, sentinel.Something, "non-test method patched") Foo = patch('%s.something' % __name__)(Foo) f = Foo() f.test_method() f.not_test_method() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") self.assertEqual(PTModule.something, sentinel.Something, "patch not restored") def test_patchobject_twice(self): class Something(object): attribute = sentinel.Original next_attribute = sentinel.Original2 @patch.object(Something, 'attribute', sentinel.Patched) @patch.object(Something, 'attribute', sentinel.Patched) def test(): self.assertEqual(Something.attribute, sentinel.Patched, "unpatched") test() self.assertEqual(Something.attribute, sentinel.Original, "patch not restored") def test_patch_dict(self): foo = {'initial': object(), 'other': 'something'} original = foo.copy() @patch.dict(foo) def test(): foo['a'] = 3 del foo['initial'] foo['other'] = 'something else' test() self.assertEqual(foo, original) @patch.dict(foo, {'a': 'b'}) def test(): self.assertEqual(len(foo), 3) self.assertEqual(foo['a'], 'b') test() self.assertEqual(foo, original) @patch.dict(foo, [('a', 'b')]) def test(): self.assertEqual(len(foo), 3) self.assertEqual(foo['a'], 'b') test() self.assertEqual(foo, original) def test_patch_dict_with_container_object(self): foo = Container() foo['initial'] = object() foo['other'] = 'something' original = foo.values.copy() @patch.dict(foo) def test(): foo['a'] = 3 del foo['initial'] foo['other'] = 'something else' test() self.assertEqual(foo.values, original) @patch.dict(foo, {'a': 'b'}) def test(): self.assertEqual(len(foo.values), 3) self.assertEqual(foo['a'], 'b') test() self.assertEqual(foo.values, original) def test_patch_dict_with_clear(self): foo = {'initial': object(), 'other': 'something'} original = foo.copy() @patch.dict(foo, clear=True) def test(): self.assertEqual(foo, {}) foo['a'] = 3 foo['other'] = 'something else' test() self.assertEqual(foo, original) @patch.dict(foo, {'a': 'b'}, clear=True) def test(): self.assertEqual(foo, {'a': 'b'}) test() self.assertEqual(foo, original) @patch.dict(foo, [('a', 'b')], clear=True) def test(): self.assertEqual(foo, {'a': 'b'}) test() self.assertEqual(foo, original) def test_patch_dict_with_container_object_and_clear(self): foo = Container() foo['initial'] = object() foo['other'] = 'something' original = foo.values.copy() @patch.dict(foo, clear=True) def test(): self.assertEqual(foo.values, {}) foo['a'] = 3 foo['other'] = 'something else' test() self.assertEqual(foo.values, original) @patch.dict(foo, {'a': 'b'}, clear=True) def test(): self.assertEqual(foo.values, {'a': 'b'}) test() self.assertEqual(foo.values, original) def test_patch_dict_as_context_manager(self): foo = {'a': 'b'} with patch.dict(foo, a='c') as patched: self.assertEqual(patched, {'a': 'c'}) self.assertEqual(foo, {'a': 'b'}) def test_name_preserved(self): foo = {} @patch('%s.SomeClass' % __name__, object()) @patch('%s.SomeClass' % __name__, object(), autospec=True) @patch.object(SomeClass, object()) @patch.dict(foo) def some_name(): pass self.assertEqual(some_name.__name__, 'some_name') def test_patch_with_exception(self): foo = {} @patch.dict(foo, {'a': 'b'}) def test(): raise NameError('Konrad') with self.assertRaises(NameError): test() self.assertEqual(foo, {}) def test_patch_dict_with_string(self): @patch.dict('os.environ', {'konrad_delong': 'some value'}) def test(): self.assertIn('konrad_delong', os.environ) test() def test_patch_dict_decorator_resolution(self): # bpo-35512: Ensure that patch with a string target resolves to # the new dictionary during function call original = support.target.copy() @patch.dict('mock.tests.support.target', {'bar': 'BAR'}) def test(): self.assertEqual(support.target, {'foo': 'BAZ', 'bar': 'BAR'}) try: support.target = {'foo': 'BAZ'} test() self.assertEqual(support.target, {'foo': 'BAZ'}) finally: support.target = original def test_patch_spec_set(self): @patch('%s.SomeClass' % __name__, spec=SomeClass, spec_set=True) def test(MockClass): MockClass.z = 'foo' self.assertRaises(AttributeError, test) @patch.object(support, 'SomeClass', spec=SomeClass, spec_set=True) def test(MockClass): MockClass.z = 'foo' self.assertRaises(AttributeError, test) @patch('%s.SomeClass' % __name__, spec_set=True) def test(MockClass): MockClass.z = 'foo' self.assertRaises(AttributeError, test) @patch.object(support, 'SomeClass', spec_set=True) def test(MockClass): MockClass.z = 'foo' self.assertRaises(AttributeError, test) def test_spec_set_inherit(self): @patch('%s.SomeClass' % __name__, spec_set=True) def test(MockClass): instance = MockClass() instance.z = 'foo' self.assertRaises(AttributeError, test) def test_patch_start_stop(self): original = something patcher = patch('%s.something' % __name__) self.assertIs(something, original) mock = patcher.start() try: self.assertIsNot(mock, original) self.assertIs(something, mock) finally: patcher.stop() self.assertIs(something, original) def test_stop_without_start(self): # bpo-36366: calling stop without start will return None. patcher = patch(foo_name, 'bar', 3) self.assertIsNone(patcher.stop()) def test_stop_idempotent(self): # bpo-36366: calling stop on an already stopped patch will return None. patcher = patch(foo_name, 'bar', 3) patcher.start() patcher.stop() self.assertIsNone(patcher.stop()) def test_patchobject_start_stop(self): original = something patcher = patch.object(PTModule, 'something', 'foo') self.assertIs(something, original) replaced = patcher.start() try: self.assertEqual(replaced, 'foo') self.assertIs(something, replaced) finally: patcher.stop() self.assertIs(something, original) def test_patch_dict_start_stop(self): d = {'foo': 'bar'} original = d.copy() patcher = patch.dict(d, [('spam', 'eggs')], clear=True) self.assertEqual(d, original) patcher.start() try: self.assertEqual(d, {'spam': 'eggs'}) finally: patcher.stop() self.assertEqual(d, original) def test_patch_dict_stop_without_start(self): d = {'foo': 'bar'} original = d.copy() patcher = patch.dict(d, [('spam', 'eggs')], clear=True) self.assertFalse(patcher.stop()) self.assertEqual(d, original) def test_patch_dict_class_decorator(self): this = self d = {'spam': 'eggs'} original = d.copy() class Test(object): def test_first(self): this.assertEqual(d, {'foo': 'bar'}) def test_second(self): this.assertEqual(d, {'foo': 'bar'}) Test = patch.dict(d, {'foo': 'bar'}, clear=True)(Test) self.assertEqual(d, original) test = Test() test.test_first() self.assertEqual(d, original) test.test_second() self.assertEqual(d, original) test = Test() test.test_first() self.assertEqual(d, original) test.test_second() self.assertEqual(d, original) def test_get_only_proxy(self): class Something(object): foo = 'foo' class SomethingElse: foo = 'foo' for thing in Something, SomethingElse, Something(), SomethingElse: proxy = _get_proxy(thing) @patch.object(proxy, 'foo', 'bar') def test(): self.assertEqual(proxy.foo, 'bar') test() self.assertEqual(proxy.foo, 'foo') self.assertEqual(thing.foo, 'foo') self.assertNotIn('foo', proxy.__dict__) def test_get_set_delete_proxy(self): class Something(object): foo = 'foo' class SomethingElse: foo = 'foo' for thing in Something, SomethingElse, Something(), SomethingElse: proxy = _get_proxy(Something, get_only=False) @patch.object(proxy, 'foo', 'bar') def test(): self.assertEqual(proxy.foo, 'bar') test() self.assertEqual(proxy.foo, 'foo') self.assertEqual(thing.foo, 'foo') self.assertNotIn('foo', proxy.__dict__) def test_patch_keyword_args(self): kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33, 'foo': MagicMock()} patcher = patch(foo_name, **kwargs) mock = patcher.start() patcher.stop() self.assertRaises(KeyError, mock) self.assertEqual(mock.foo.bar(), 33) self.assertIsInstance(mock.foo, MagicMock) def test_patch_object_keyword_args(self): kwargs = {'side_effect': KeyError, 'foo.bar.return_value': 33, 'foo': MagicMock()} patcher = patch.object(Foo, 'f', **kwargs) mock = patcher.start() patcher.stop() self.assertRaises(KeyError, mock) self.assertEqual(mock.foo.bar(), 33) self.assertIsInstance(mock.foo, MagicMock) def test_patch_dict_keyword_args(self): original = {'foo': 'bar'} copy = original.copy() patcher = patch.dict(original, foo=3, bar=4, baz=5) patcher.start() try: self.assertEqual(original, dict(foo=3, bar=4, baz=5)) finally: patcher.stop() self.assertEqual(original, copy) def test_autospec(self): class Boo(object): def __init__(self, a): pass def f(self, a): pass def g(self): pass foo = 'bar' class Bar(object): def a(self): pass def _test(mock): mock(1) mock.assert_called_with(1) self.assertRaises(TypeError, mock) def _test2(mock): mock.f(1) mock.f.assert_called_with(1) self.assertRaises(TypeError, mock.f) mock.g() mock.g.assert_called_with() self.assertRaises(TypeError, mock.g, 1) self.assertRaises(AttributeError, getattr, mock, 'h') mock.foo.lower() mock.foo.lower.assert_called_with() self.assertRaises(AttributeError, getattr, mock.foo, 'bar') mock.Bar() mock.Bar.assert_called_with() mock.Bar.a() mock.Bar.a.assert_called_with() self.assertRaises(TypeError, mock.Bar.a, 1) mock.Bar().a() mock.Bar().a.assert_called_with() self.assertRaises(TypeError, mock.Bar().a, 1) self.assertRaises(AttributeError, getattr, mock.Bar, 'b') self.assertRaises(AttributeError, getattr, mock.Bar(), 'b') def function(mock): _test(mock) _test2(mock) _test2(mock(1)) self.assertIs(mock, Foo) return mock test = patch(foo_name, autospec=True)(function) mock = test() self.assertIsNot(Foo, mock) # test patching a second time works test() module = sys.modules[__name__] test = patch.object(module, 'Foo', autospec=True)(function) mock = test() self.assertIsNot(Foo, mock) # test patching a second time works test() def test_autospec_function(self): @patch('%s.function' % __name__, autospec=True) def test(mock): function.assert_not_called() self.assertRaises(AssertionError, function.assert_called) self.assertRaises(AssertionError, function.assert_called_once) function(1) self.assertRaises(AssertionError, function.assert_not_called) function.assert_called_with(1) function.assert_called() function.assert_called_once() function(2, 3) function.assert_called_with(2, 3) self.assertRaises(TypeError, function) self.assertRaises(AttributeError, getattr, function, 'foo') test() def test_autospec_keywords(self): @patch('%s.function' % __name__, autospec=True, return_value=3) def test(mock_function): #self.assertEqual(function.abc, 'foo') return function(1, 2) result = test() self.assertEqual(result, 3) def test_autospec_staticmethod(self): with patch('%s.Foo.static_method' % __name__, autospec=True) as method: Foo.static_method() method.assert_called_once_with() def test_autospec_classmethod(self): with patch('%s.Foo.class_method' % __name__, autospec=True) as method: Foo.class_method() method.assert_called_once_with() def test_autospec_with_new(self): patcher = patch('%s.function' % __name__, new=3, autospec=True) self.assertRaises(TypeError, patcher.start) module = sys.modules[__name__] patcher = patch.object(module, 'function', new=3, autospec=True) self.assertRaises(TypeError, patcher.start) def test_autospec_with_object(self): class Bar(Foo): extra = [] patcher = patch(foo_name, autospec=Bar) mock = patcher.start() try: self.assertIsInstance(mock, Bar) self.assertIsInstance(mock.extra, list) finally: patcher.stop() def test_autospec_inherits(self): FooClass = Foo patcher = patch(foo_name, autospec=True) mock = patcher.start() try: self.assertIsInstance(mock, FooClass) self.assertIsInstance(mock(3), FooClass) finally: patcher.stop() def test_autospec_name(self): patcher = patch(foo_name, autospec=True) mock = patcher.start() try: self.assertIn(" name='Foo'", repr(mock)) self.assertIn(" name='Foo.f'", repr(mock.f)) self.assertIn(" name='Foo()'", repr(mock(None))) self.assertIn(" name='Foo().f'", repr(mock(None).f)) finally: patcher.stop() def test_tracebacks(self): @patch.object(Foo, 'f', object()) def test(): raise AssertionError try: test() except: err = sys.exc_info() result = unittest.TextTestResult(None, None, 0) traceback = result._exc_info_to_string(err, self) self.assertIn('raise AssertionError', traceback) def test_new_callable_patch(self): patcher = patch(foo_name, new_callable=NonCallableMagicMock) m1 = patcher.start() patcher.stop() m2 = patcher.start() patcher.stop() self.assertIsNot(m1, m2) for mock in m1, m2: self.assertNotCallable(m1) def test_new_callable_patch_object(self): patcher = patch.object(Foo, 'f', new_callable=NonCallableMagicMock) m1 = patcher.start() patcher.stop() m2 = patcher.start() patcher.stop() self.assertIsNot(m1, m2) for mock in m1, m2: self.assertNotCallable(m1) def test_new_callable_keyword_arguments(self): class Bar(object): kwargs = None def __init__(self, **kwargs): Bar.kwargs = kwargs patcher = patch(foo_name, new_callable=Bar, arg1=1, arg2=2) m = patcher.start() try: self.assertIs(type(m), Bar) self.assertEqual(Bar.kwargs, dict(arg1=1, arg2=2)) finally: patcher.stop() def test_new_callable_spec(self): class Bar(object): kwargs = None def __init__(self, **kwargs): Bar.kwargs = kwargs patcher = patch(foo_name, new_callable=Bar, spec=Bar) patcher.start() try: self.assertEqual(Bar.kwargs, dict(spec=Bar)) finally: patcher.stop() patcher = patch(foo_name, new_callable=Bar, spec_set=Bar) patcher.start() try: self.assertEqual(Bar.kwargs, dict(spec_set=Bar)) finally: patcher.stop() def test_new_callable_create(self): non_existent_attr = '%s.weeeee' % foo_name p = patch(non_existent_attr, new_callable=NonCallableMock) self.assertRaises(AttributeError, p.start) p = patch(non_existent_attr, new_callable=NonCallableMock, create=True) m = p.start() try: self.assertNotCallable(m, magic=False) finally: p.stop() def test_new_callable_incompatible_with_new(self): self.assertRaises( ValueError, patch, foo_name, new=object(), new_callable=MagicMock ) self.assertRaises( ValueError, patch.object, Foo, 'f', new=object(), new_callable=MagicMock ) def test_new_callable_incompatible_with_autospec(self): self.assertRaises( ValueError, patch, foo_name, new_callable=MagicMock, autospec=True ) self.assertRaises( ValueError, patch.object, Foo, 'f', new_callable=MagicMock, autospec=True ) def test_new_callable_inherit_for_mocks(self): class MockSub(Mock): pass MockClasses = ( NonCallableMock, NonCallableMagicMock, MagicMock, Mock, MockSub ) for Klass in MockClasses: for arg in 'spec', 'spec_set': kwargs = {arg: True} p = patch(foo_name, new_callable=Klass, **kwargs) m = p.start() try: instance = m.return_value self.assertRaises(AttributeError, getattr, instance, 'x') finally: p.stop() def test_new_callable_inherit_non_mock(self): class NotAMock(object): def __init__(self, spec): self.spec = spec p = patch(foo_name, new_callable=NotAMock, spec=True) m = p.start() try: self.assertTrue(is_instance(m, NotAMock)) self.assertRaises(AttributeError, getattr, m, 'return_value') finally: p.stop() self.assertEqual(m.spec, Foo) def test_new_callable_class_decorating(self): test = self original = Foo class SomeTest(object): def _test(self, mock_foo): test.assertIsNot(Foo, original) test.assertIs(Foo, mock_foo) test.assertIsInstance(Foo, SomeClass) def test_two(self, mock_foo): self._test(mock_foo) def test_one(self, mock_foo): self._test(mock_foo) SomeTest = patch(foo_name, new_callable=SomeClass)(SomeTest) SomeTest().test_one() SomeTest().test_two() self.assertIs(Foo, original) def test_patch_multiple(self): original_foo = Foo original_f = Foo.f original_g = Foo.g patcher1 = patch.multiple(foo_name, f=1, g=2) patcher2 = patch.multiple(Foo, f=1, g=2) for patcher in patcher1, patcher2: patcher.start() try: self.assertIs(Foo, original_foo) self.assertEqual(Foo.f, 1) self.assertEqual(Foo.g, 2) finally: patcher.stop() self.assertIs(Foo, original_foo) self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) @patch.multiple(foo_name, f=3, g=4) def test(): self.assertIs(Foo, original_foo) self.assertEqual(Foo.f, 3) self.assertEqual(Foo.g, 4) test() def test_patch_multiple_no_kwargs(self): self.assertRaises(ValueError, patch.multiple, foo_name) self.assertRaises(ValueError, patch.multiple, Foo) def test_patch_multiple_create_mocks(self): original_foo = Foo original_f = Foo.f original_g = Foo.g @patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT) def test(f, foo): self.assertIs(Foo, original_foo) self.assertIs(Foo.f, f) self.assertEqual(Foo.g, 3) self.assertIs(Foo.foo, foo) self.assertTrue(is_instance(f, MagicMock)) self.assertTrue(is_instance(foo, MagicMock)) test() self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_create_mocks_different_order(self): original_f = Foo.f original_g = Foo.g patcher = patch.object(Foo, 'f', 3) patcher.attribute_name = 'f' other = patch.object(Foo, 'g', DEFAULT) other.attribute_name = 'g' patcher.additional_patchers = [other] @patcher def test(g): self.assertIs(Foo.g, g) self.assertEqual(Foo.f, 3) test() self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_stacked_decorators(self): original_foo = Foo original_f = Foo.f original_g = Foo.g @patch.multiple(foo_name, f=DEFAULT) @patch.multiple(foo_name, foo=DEFAULT) @patch(foo_name + '.g') def test1(g, **kwargs): _test(g, **kwargs) @patch.multiple(foo_name, f=DEFAULT) @patch(foo_name + '.g') @patch.multiple(foo_name, foo=DEFAULT) def test2(g, **kwargs): _test(g, **kwargs) @patch(foo_name + '.g') @patch.multiple(foo_name, f=DEFAULT) @patch.multiple(foo_name, foo=DEFAULT) def test3(g, **kwargs): _test(g, **kwargs) def _test(g, **kwargs): f = kwargs.pop('f') foo = kwargs.pop('foo') self.assertFalse(kwargs) self.assertIs(Foo, original_foo) self.assertIs(Foo.f, f) self.assertIs(Foo.g, g) self.assertIs(Foo.foo, foo) self.assertTrue(is_instance(f, MagicMock)) self.assertTrue(is_instance(g, MagicMock)) self.assertTrue(is_instance(foo, MagicMock)) test1() test2() test3() self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_create_mocks_patcher(self): original_foo = Foo original_f = Foo.f original_g = Foo.g patcher = patch.multiple(foo_name, f=DEFAULT, g=3, foo=DEFAULT) result = patcher.start() try: f = result['f'] foo = result['foo'] self.assertEqual(set(result), set(['f', 'foo'])) self.assertIs(Foo, original_foo) self.assertIs(Foo.f, f) self.assertIs(Foo.foo, foo) self.assertTrue(is_instance(f, MagicMock)) self.assertTrue(is_instance(foo, MagicMock)) finally: patcher.stop() self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_decorating_class(self): test = self original_foo = Foo original_f = Foo.f original_g = Foo.g class SomeTest(object): def _test(self, f, foo): test.assertIs(Foo, original_foo) test.assertIs(Foo.f, f) test.assertEqual(Foo.g, 3) test.assertIs(Foo.foo, foo) test.assertTrue(is_instance(f, MagicMock)) test.assertTrue(is_instance(foo, MagicMock)) def test_two(self, f, foo): self._test(f, foo) def test_one(self, f, foo): self._test(f, foo) SomeTest = patch.multiple( foo_name, f=DEFAULT, g=3, foo=DEFAULT )(SomeTest) thing = SomeTest() thing.test_one() thing.test_two() self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_create(self): patcher = patch.multiple(Foo, blam='blam') self.assertRaises(AttributeError, patcher.start) patcher = patch.multiple(Foo, blam='blam', create=True) patcher.start() try: self.assertEqual(Foo.blam, 'blam') finally: patcher.stop() self.assertFalse(hasattr(Foo, 'blam')) def test_patch_multiple_spec_set(self): # if spec_set works then we can assume that spec and autospec also # work as the underlying machinery is the same patcher = patch.multiple(Foo, foo=DEFAULT, spec_set=['a', 'b']) result = patcher.start() try: self.assertEqual(Foo.foo, result['foo']) Foo.foo.a(1) Foo.foo.b(2) Foo.foo.a.assert_called_with(1) Foo.foo.b.assert_called_with(2) self.assertRaises(AttributeError, setattr, Foo.foo, 'c', None) finally: patcher.stop() def test_patch_multiple_new_callable(self): class Thing(object): pass patcher = patch.multiple( Foo, f=DEFAULT, g=DEFAULT, new_callable=Thing ) result = patcher.start() try: self.assertIs(Foo.f, result['f']) self.assertIs(Foo.g, result['g']) self.assertIsInstance(Foo.f, Thing) self.assertIsInstance(Foo.g, Thing) self.assertIsNot(Foo.f, Foo.g) finally: patcher.stop() def test_nested_patch_failure(self): original_f = Foo.f original_g = Foo.g @patch.object(Foo, 'g', 1) @patch.object(Foo, 'missing', 1) @patch.object(Foo, 'f', 1) def thing1(): pass @patch.object(Foo, 'missing', 1) @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) def thing2(): pass @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) @patch.object(Foo, 'missing', 1) def thing3(): pass for func in thing1, thing2, thing3: self.assertRaises(AttributeError, func) self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_new_callable_failure(self): original_f = Foo.f original_g = Foo.g original_foo = Foo.foo def crasher(): raise NameError('crasher') @patch.object(Foo, 'g', 1) @patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'f', 1) def thing1(): pass @patch.object(Foo, 'foo', new_callable=crasher) @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) def thing2(): pass @patch.object(Foo, 'g', 1) @patch.object(Foo, 'f', 1) @patch.object(Foo, 'foo', new_callable=crasher) def thing3(): pass for func in thing1, thing2, thing3: self.assertRaises(NameError, func) self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) self.assertEqual(Foo.foo, original_foo) def test_patch_multiple_failure(self): original_f = Foo.f original_g = Foo.g patcher = patch.object(Foo, 'f', 1) patcher.attribute_name = 'f' good = patch.object(Foo, 'g', 1) good.attribute_name = 'g' bad = patch.object(Foo, 'missing', 1) bad.attribute_name = 'missing' for additionals in [good, bad], [bad, good]: patcher.additional_patchers = additionals @patcher def func(): pass self.assertRaises(AttributeError, func) self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) def test_patch_multiple_new_callable_failure(self): original_f = Foo.f original_g = Foo.g original_foo = Foo.foo def crasher(): raise NameError('crasher') patcher = patch.object(Foo, 'f', 1) patcher.attribute_name = 'f' good = patch.object(Foo, 'g', 1) good.attribute_name = 'g' bad = patch.object(Foo, 'foo', new_callable=crasher) bad.attribute_name = 'foo' for additionals in [good, bad], [bad, good]: patcher.additional_patchers = additionals @patcher def func(): pass self.assertRaises(NameError, func) self.assertEqual(Foo.f, original_f) self.assertEqual(Foo.g, original_g) self.assertEqual(Foo.foo, original_foo) def test_patch_multiple_string_subclasses(self): Foo = type('Foo', (str,), {'fish': 'tasty'}) foo = Foo() @patch.multiple(foo, fish='nearly gone') def test(): self.assertEqual(foo.fish, 'nearly gone') test() self.assertEqual(foo.fish, 'tasty') @patch('mock.patch.TEST_PREFIX', 'foo') def test_patch_test_prefix(self): class Foo(object): thing = 'original' def foo_one(self): return self.thing def foo_two(self): return self.thing def test_one(self): return self.thing def test_two(self): return self.thing Foo = patch.object(Foo, 'thing', 'changed')(Foo) foo = Foo() self.assertEqual(foo.foo_one(), 'changed') self.assertEqual(foo.foo_two(), 'changed') self.assertEqual(foo.test_one(), 'original') self.assertEqual(foo.test_two(), 'original') @patch('mock.patch.TEST_PREFIX', 'bar') def test_patch_dict_test_prefix(self): class Foo(object): def bar_one(self): return dict(the_dict) def bar_two(self): return dict(the_dict) def test_one(self): return dict(the_dict) def test_two(self): return dict(the_dict) the_dict = {'key': 'original'} Foo = patch.dict(the_dict, key='changed')(Foo) foo =Foo() self.assertEqual(foo.bar_one(), {'key': 'changed'}) self.assertEqual(foo.bar_two(), {'key': 'changed'}) self.assertEqual(foo.test_one(), {'key': 'original'}) self.assertEqual(foo.test_two(), {'key': 'original'}) def test_patch_with_spec_mock_repr(self): for arg in ('spec', 'autospec', 'spec_set'): p = patch('%s.SomeClass' % __name__, **{arg: True}) m = p.start() try: self.assertIn(" name='SomeClass'", repr(m)) self.assertIn(" name='SomeClass.class_attribute'", repr(m.class_attribute)) self.assertIn(" name='SomeClass()'", repr(m())) self.assertIn(" name='SomeClass().class_attribute'", repr(m().class_attribute)) finally: p.stop() def test_patch_nested_autospec_repr(self): with patch('mock.tests.support', autospec=True) as m: self.assertIn(" name='support.SomeClass.wibble()'", repr(m.SomeClass.wibble())) self.assertIn(" name='support.SomeClass().wibble()'", repr(m.SomeClass().wibble())) def test_mock_calls_with_patch(self): for arg in ('spec', 'autospec', 'spec_set'): p = patch('%s.SomeClass' % __name__, **{arg: True}) m = p.start() try: m.wibble() kalls = [call.wibble()] self.assertEqual(m.mock_calls, kalls) self.assertEqual(m.method_calls, kalls) self.assertEqual(m.wibble.mock_calls, [call()]) result = m() kalls.append(call()) self.assertEqual(m.mock_calls, kalls) result.wibble() kalls.append(call().wibble()) self.assertEqual(m.mock_calls, kalls) self.assertEqual(result.mock_calls, [call.wibble()]) self.assertEqual(result.wibble.mock_calls, [call()]) self.assertEqual(result.method_calls, [call.wibble()]) finally: p.stop() def test_patch_imports_lazily(self): p1 = patch('squizz.squozz') self.assertRaises(ImportError, p1.start) with uncache('squizz'): squizz = Mock() sys.modules['squizz'] = squizz squizz.squozz = 6 p1 = patch('squizz.squozz') squizz.squozz = 3 p1.start() p1.stop() self.assertEqual(squizz.squozz, 3) def test_patch_propagates_exc_on_exit(self): class holder: exc_info = None, None, None class custom_patch(_patch): def __exit__(self, etype=None, val=None, tb=None): _patch.__exit__(self, etype, val, tb) holder.exc_info = etype, val, tb stop = __exit__ def with_custom_patch(target): getter, attribute = _get_target(target) return custom_patch( getter, attribute, DEFAULT, None, False, None, None, None, {} ) @with_custom_patch('squizz.squozz') def test(mock): raise RuntimeError with uncache('squizz'): squizz = Mock() sys.modules['squizz'] = squizz self.assertRaises(RuntimeError, test) self.assertIs(holder.exc_info[0], RuntimeError) self.assertIsNotNone(holder.exc_info[1], 'exception value not propagated') self.assertIsNotNone(holder.exc_info[2], 'exception traceback not propagated') def test_create_and_specs(self): for kwarg in ('spec', 'spec_set', 'autospec'): p = patch('%s.doesnotexist' % __name__, create=True, **{kwarg: True}) self.assertRaises(TypeError, p.start) self.assertRaises(NameError, lambda: doesnotexist) # check that spec with create is innocuous if the original exists p = patch(MODNAME, create=True, **{kwarg: True}) p.start() p.stop() def test_multiple_specs(self): original = PTModule for kwarg in ('spec', 'spec_set'): p = patch(MODNAME, autospec=0, **{kwarg: 0}) self.assertRaises(TypeError, p.start) self.assertIs(PTModule, original) for kwarg in ('spec', 'autospec'): p = patch(MODNAME, spec_set=0, **{kwarg: 0}) self.assertRaises(TypeError, p.start) self.assertIs(PTModule, original) for kwarg in ('spec_set', 'autospec'): p = patch(MODNAME, spec=0, **{kwarg: 0}) self.assertRaises(TypeError, p.start) self.assertIs(PTModule, original) def test_specs_false_instead_of_none(self): p = patch(MODNAME, spec=False, spec_set=False, autospec=False) mock = p.start() try: # no spec should have been set, so attribute access should not fail mock.does_not_exist mock.does_not_exist = 3 finally: p.stop() def test_falsey_spec(self): for kwarg in ('spec', 'autospec', 'spec_set'): p = patch(MODNAME, **{kwarg: 0}) m = p.start() try: self.assertRaises(AttributeError, getattr, m, 'doesnotexit') finally: p.stop() def test_spec_set_true(self): for kwarg in ('spec', 'autospec'): p = patch(MODNAME, spec_set=True, **{kwarg: True}) m = p.start() try: self.assertRaises(AttributeError, setattr, m, 'doesnotexist', 'something') self.assertRaises(AttributeError, getattr, m, 'doesnotexist') finally: p.stop() def test_callable_spec_as_list(self): spec = ('__call__',) p = patch(MODNAME, spec=spec) m = p.start() try: self.assertTrue(callable(m)) finally: p.stop() def test_not_callable_spec_as_list(self): spec = ('foo', 'bar') p = patch(MODNAME, spec=spec) m = p.start() try: self.assertFalse(callable(m)) finally: p.stop() def test_patch_stopall(self): unlink = os.unlink chdir = os.chdir path = os.path patch('os.unlink', something).start() patch('os.chdir', something_else).start() @patch('os.path') def patched(mock_path): patch.stopall() self.assertIs(os.path, mock_path) self.assertIs(os.unlink, unlink) self.assertIs(os.chdir, chdir) patched() self.assertIs(os.path, path) def test_stopall_lifo(self): stopped = [] class thing(object): one = two = three = None def get_patch(attribute): class mypatch(_patch): def stop(self): stopped.append(attribute) return super(mypatch, self).stop() return mypatch(lambda: thing, attribute, None, None, False, None, None, None, {}) [get_patch(val).start() for val in ("one", "two", "three")] patch.stopall() self.assertEqual(stopped, ["three", "two", "one"]) def test_patch_dict_stopall(self): dic1 = {} dic2 = {1: 'a'} dic3 = {1: 'A', 2: 'B'} origdic1 = dic1.copy() origdic2 = dic2.copy() origdic3 = dic3.copy() patch.dict(dic1, {1: 'I', 2: 'II'}).start() patch.dict(dic2, {2: 'b'}).start() @patch.dict(dic3) def patched(): del dic3[1] patched() self.assertNotEqual(dic1, origdic1) self.assertNotEqual(dic2, origdic2) self.assertEqual(dic3, origdic3) patch.stopall() self.assertEqual(dic1, origdic1) self.assertEqual(dic2, origdic2) self.assertEqual(dic3, origdic3) def test_patch_and_patch_dict_stopall(self): original_unlink = os.unlink original_chdir = os.chdir dic1 = {} dic2 = {1: 'A', 2: 'B'} origdic1 = dic1.copy() origdic2 = dic2.copy() patch('os.unlink', something).start() patch('os.chdir', something_else).start() patch.dict(dic1, {1: 'I', 2: 'II'}).start() patch.dict(dic2).start() del dic2[1] self.assertIsNot(os.unlink, original_unlink) self.assertIsNot(os.chdir, original_chdir) self.assertNotEqual(dic1, origdic1) self.assertNotEqual(dic2, origdic2) patch.stopall() self.assertIs(os.unlink, original_unlink) self.assertIs(os.chdir, original_chdir) self.assertEqual(dic1, origdic1) self.assertEqual(dic2, origdic2) def test_special_attrs(self): def foo(x=0): """TEST""" return x with patch.object(foo, '__defaults__', (1, )): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) with patch.object(foo, '__doc__', "FUN"): self.assertEqual(foo.__doc__, "FUN") self.assertEqual(foo.__doc__, "TEST") with patch.object(foo, '__module__', "testpatch2"): self.assertEqual(foo.__module__, "testpatch2") self.assertEqual(foo.__module__, 'mock.tests.testpatch') with patch.object(foo, '__annotations__', dict([('s', 1, )])): self.assertEqual(foo.__annotations__, dict([('s', 1, )])) self.assertEqual(foo.__annotations__, dict()) def foo(*a, x=0): return x with patch.object(foo, '__kwdefaults__', dict([('x', 1, )])): self.assertEqual(foo(), 1) self.assertEqual(foo(), 0) def test_patch_orderdict(self): foo = OrderedDict() foo['a'] = object() foo['b'] = 'python' original = foo.copy() update_values = list(zip('cdefghijklmnopqrstuvwxyz', range(26))) patched_values = list(foo.items()) + update_values with patch.dict(foo, OrderedDict(update_values)): self.assertEqual(list(foo.items()), patched_values) self.assertEqual(foo, original) with patch.dict(foo, update_values): self.assertEqual(list(foo.items()), patched_values) self.assertEqual(foo, original) def test_dotted_but_module_not_loaded(self): # This exercises the AttributeError branch of _dot_lookup. # make sure it's there import mock.tests.support # now make sure it's not: with patch.dict('sys.modules'): del sys.modules['mock.tests.support'] del sys.modules['mock.tests'] del sys.modules['mock.mock'] del sys.modules['mock'] # now make sure we can patch based on a dotted path: @patch('mock.tests.support.X') def test(mock): pass test() def test_invalid_target(self): with self.assertRaises(TypeError): patch('') def test_cant_set_kwargs_when_passing_a_mock(self): @patch('mock.tests.support.X', new=object(), x=1) def test(): pass with self.assertRaises(TypeError): test() if __name__ == '__main__': unittest.main() mock-4.0.3/mock/tests/testsealable.py000066400000000000000000000115651376434722300176070ustar00rootroot00000000000000import unittest import mock class SampleObject: def method_sample1(self): pass def method_sample2(self): pass class TestSealable(unittest.TestCase): def test_attributes_return_more_mocks_by_default(self): m = mock.Mock() self.assertIsInstance(m.test, mock.Mock) self.assertIsInstance(m.test(), mock.Mock) self.assertIsInstance(m.test().test2(), mock.Mock) def test_new_attributes_cannot_be_accessed_on_seal(self): m = mock.Mock() mock.seal(m) with self.assertRaises(AttributeError): m.test with self.assertRaises(AttributeError): m() def test_new_attributes_cannot_be_set_on_seal(self): m = mock.Mock() mock.seal(m) with self.assertRaises(AttributeError): m.test = 1 def test_existing_attributes_can_be_set_on_seal(self): m = mock.Mock() m.test.test2 = 1 mock.seal(m) m.test.test2 = 2 self.assertEqual(m.test.test2, 2) def test_new_attributes_cannot_be_set_on_child_of_seal(self): m = mock.Mock() m.test.test2 = 1 mock.seal(m) with self.assertRaises(AttributeError): m.test.test3 = 1 def test_existing_attributes_allowed_after_seal(self): m = mock.Mock() m.test.return_value = 3 mock.seal(m) self.assertEqual(m.test(), 3) def test_initialized_attributes_allowed_after_seal(self): m = mock.Mock(test_value=1) mock.seal(m) self.assertEqual(m.test_value, 1) def test_call_on_sealed_mock_fails(self): m = mock.Mock() mock.seal(m) with self.assertRaises(AttributeError): m() def test_call_on_defined_sealed_mock_succeeds(self): m = mock.Mock(return_value=5) mock.seal(m) self.assertEqual(m(), 5) def test_seals_recurse_on_added_attributes(self): m = mock.Mock() m.test1.test2().test3 = 4 mock.seal(m) self.assertEqual(m.test1.test2().test3, 4) with self.assertRaises(AttributeError): m.test1.test2().test4 with self.assertRaises(AttributeError): m.test1.test3 def test_seals_recurse_on_magic_methods(self): m = mock.MagicMock() m.test1.test2["a"].test3 = 4 m.test1.test3[2:5].test3 = 4 mock.seal(m) self.assertEqual(m.test1.test2["a"].test3, 4) self.assertEqual(m.test1.test2[2:5].test3, 4) with self.assertRaises(AttributeError): m.test1.test2["a"].test4 with self.assertRaises(AttributeError): m.test1.test3[2:5].test4 def test_seals_dont_recurse_on_manual_attributes(self): m = mock.Mock(name="root_mock") m.test1.test2 = mock.Mock(name="not_sealed") m.test1.test2.test3 = 4 mock.seal(m) self.assertEqual(m.test1.test2.test3, 4) m.test1.test2.test4 # Does not raise m.test1.test2.test4 = 1 # Does not raise def test_integration_with_spec_att_definition(self): """You are not restricted when using mock with spec""" m = mock.Mock(SampleObject) m.attr_sample1 = 1 m.attr_sample3 = 3 mock.seal(m) self.assertEqual(m.attr_sample1, 1) self.assertEqual(m.attr_sample3, 3) with self.assertRaises(AttributeError): m.attr_sample2 def test_integration_with_spec_method_definition(self): """You need to defin the methods, even if they are in the spec""" m = mock.Mock(SampleObject) m.method_sample1.return_value = 1 mock.seal(m) self.assertEqual(m.method_sample1(), 1) with self.assertRaises(AttributeError): m.method_sample2() def test_integration_with_spec_method_definition_respects_spec(self): """You cannot define methods out of the spec""" m = mock.Mock(SampleObject) with self.assertRaises(AttributeError): m.method_sample3.return_value = 3 def test_sealed_exception_has_attribute_name(self): m = mock.Mock() mock.seal(m) with self.assertRaises(AttributeError) as cm: m.SECRETE_name self.assertIn("SECRETE_name", str(cm.exception)) def test_attribute_chain_is_maintained(self): m = mock.Mock(name="mock_name") m.test1.test2.test3.test4 mock.seal(m) with self.assertRaises(AttributeError) as cm: m.test1.test2.test3.test4.boom self.assertIn("mock_name.test1.test2.test3.test4.boom", str(cm.exception)) def test_call_chain_is_maintained(self): m = mock.Mock() m.test1().test2.test3().test4 mock.seal(m) with self.assertRaises(AttributeError) as cm: m.test1().test2.test3().test4() self.assertIn("mock.test1().test2.test3().test4", str(cm.exception)) if __name__ == "__main__": unittest.main() mock-4.0.3/mock/tests/testsentinel.py000066400000000000000000000024441376434722300176540ustar00rootroot00000000000000import unittest import copy import pickle from mock import sentinel, DEFAULT class SentinelTest(unittest.TestCase): def testSentinels(self): self.assertEqual(sentinel.whatever, sentinel.whatever, 'sentinel not stored') self.assertNotEqual(sentinel.whatever, sentinel.whateverelse, 'sentinel should be unique') def testSentinelName(self): self.assertEqual(str(sentinel.whatever), 'sentinel.whatever', 'sentinel name incorrect') def testDEFAULT(self): self.assertIs(DEFAULT, sentinel.DEFAULT) def testBases(self): # If this doesn't raise an AttributeError then help(mock) is broken self.assertRaises(AttributeError, lambda: sentinel.__bases__) def testPickle(self): for proto in range(pickle.HIGHEST_PROTOCOL+1): with self.subTest(protocol=proto): pickled = pickle.dumps(sentinel.whatever, proto) unpickled = pickle.loads(pickled) self.assertIs(unpickled, sentinel.whatever) def testCopy(self): self.assertIs(copy.copy(sentinel.whatever), sentinel.whatever) self.assertIs(copy.deepcopy(sentinel.whatever), sentinel.whatever) if __name__ == '__main__': unittest.main() mock-4.0.3/mock/tests/testwith.py000066400000000000000000000277161376434722300170170ustar00rootroot00000000000000import unittest from warnings import catch_warnings from mock.tests.support import is_instance from mock import MagicMock, Mock, patch, sentinel, mock_open, call something = sentinel.Something something_else = sentinel.SomethingElse class SampleException(Exception): pass class WithTest(unittest.TestCase): def test_with_statement(self): with patch('%s.something' % __name__, sentinel.Something2): self.assertEqual(something, sentinel.Something2, "unpatched") self.assertEqual(something, sentinel.Something) def test_with_statement_exception(self): with self.assertRaises(SampleException): with patch('%s.something' % __name__, sentinel.Something2): self.assertEqual(something, sentinel.Something2, "unpatched") raise SampleException() self.assertEqual(something, sentinel.Something) def test_with_statement_as(self): with patch('%s.something' % __name__) as mock_something: self.assertEqual(something, mock_something, "unpatched") self.assertTrue(is_instance(mock_something, MagicMock), "patching wrong type") self.assertEqual(something, sentinel.Something) def test_patch_object_with_statement(self): class Foo(object): something = 'foo' original = Foo.something with patch.object(Foo, 'something'): self.assertNotEqual(Foo.something, original, "unpatched") self.assertEqual(Foo.something, original) def test_with_statement_nested(self): with catch_warnings(record=True): with patch('%s.something' % __name__) as mock_something, patch('%s.something_else' % __name__) as mock_something_else: self.assertEqual(something, mock_something, "unpatched") self.assertEqual(something_else, mock_something_else, "unpatched") self.assertEqual(something, sentinel.Something) self.assertEqual(something_else, sentinel.SomethingElse) def test_with_statement_specified(self): with patch('%s.something' % __name__, sentinel.Patched) as mock_something: self.assertEqual(something, mock_something, "unpatched") self.assertEqual(mock_something, sentinel.Patched, "wrong patch") self.assertEqual(something, sentinel.Something) def testContextManagerMocking(self): mock = Mock() mock.__enter__ = Mock() mock.__exit__ = Mock() mock.__exit__.return_value = False with mock as m: self.assertEqual(m, mock.__enter__.return_value) mock.__enter__.assert_called_with() mock.__exit__.assert_called_with(None, None, None) def test_context_manager_with_magic_mock(self): mock = MagicMock() with self.assertRaises(TypeError): with mock: 'foo' + 3 mock.__enter__.assert_called_with() self.assertTrue(mock.__exit__.called) def test_with_statement_same_attribute(self): with patch('%s.something' % __name__, sentinel.Patched) as mock_something: self.assertEqual(something, mock_something, "unpatched") with patch('%s.something' % __name__) as mock_again: self.assertEqual(something, mock_again, "unpatched") self.assertEqual(something, mock_something, "restored with wrong instance") self.assertEqual(something, sentinel.Something, "not restored") def test_with_statement_imbricated(self): with patch('%s.something' % __name__) as mock_something: self.assertEqual(something, mock_something, "unpatched") with patch('%s.something_else' % __name__) as mock_something_else: self.assertEqual(something_else, mock_something_else, "unpatched") self.assertEqual(something, sentinel.Something) self.assertEqual(something_else, sentinel.SomethingElse) def test_dict_context_manager(self): foo = {} with patch.dict(foo, {'a': 'b'}): self.assertEqual(foo, {'a': 'b'}) self.assertEqual(foo, {}) with self.assertRaises(NameError): with patch.dict(foo, {'a': 'b'}): self.assertEqual(foo, {'a': 'b'}) raise NameError('Konrad') self.assertEqual(foo, {}) def test_double_patch_instance_method(self): class C: def f(self): pass c = C() with patch.object(c, 'f', autospec=True) as patch1: with patch.object(c, 'f', autospec=True) as patch2: c.f() self.assertEqual(patch2.call_count, 1) self.assertEqual(patch1.call_count, 0) c.f() self.assertEqual(patch1.call_count, 1) class TestMockOpen(unittest.TestCase): def test_mock_open(self): mock = mock_open() with patch('%s.open' % __name__, mock, create=True) as patched: self.assertIs(patched, mock) open('foo') mock.assert_called_once_with('foo') def test_mock_open_context_manager(self): mock = mock_open() handle = mock.return_value with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() expected_calls = [call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) self.assertIs(f, handle) def test_mock_open_context_manager_multiple_times(self): mock = mock_open() with patch('%s.open' % __name__, mock, create=True): with open('foo') as f: f.read() with open('bar') as f: f.read() expected_calls = [ call('foo'), call().__enter__(), call().read(), call().__exit__(None, None, None), call('bar'), call().__enter__(), call().read(), call().__exit__(None, None, None)] self.assertEqual(mock.mock_calls, expected_calls) def test_explicit_mock(self): mock = MagicMock() mock_open(mock) with patch('%s.open' % __name__, mock, create=True) as patched: self.assertIs(patched, mock) open('foo') mock.assert_called_once_with('foo') def test_read_data(self): mock = mock_open(read_data='foo') with patch('%s.open' % __name__, mock, create=True): h = open('bar') result = h.read() self.assertEqual(result, 'foo') def test_readline_data(self): # Check that readline will return all the lines from the fake file # And that once fully consumed, readline will return an empty string. mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') line1 = h.readline() line2 = h.readline() line3 = h.readline() self.assertEqual(line1, 'foo\n') self.assertEqual(line2, 'bar\n') self.assertEqual(line3, 'baz\n') self.assertEqual(h.readline(), '') # Check that we properly emulate a file that doesn't end in a newline mock = mock_open(read_data='foo') with patch('%s.open' % __name__, mock, create=True): h = open('bar') result = h.readline() self.assertEqual(result, 'foo') self.assertEqual(h.readline(), '') def test_dunder_iter_data(self): # Check that dunder_iter will return all the lines from the fake file. mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') lines = [l for l in h] self.assertEqual(lines[0], 'foo\n') self.assertEqual(lines[1], 'bar\n') self.assertEqual(lines[2], 'baz\n') self.assertEqual(h.readline(), '') with self.assertRaises(StopIteration): next(h) def test_next_data(self): # Check that next will correctly return the next available # line and plays well with the dunder_iter part. mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') line1 = next(h) line2 = next(h) lines = [l for l in h] self.assertEqual(line1, 'foo\n') self.assertEqual(line2, 'bar\n') self.assertEqual(lines[0], 'baz\n') self.assertEqual(h.readline(), '') def test_readlines_data(self): # Test that emulating a file that ends in a newline character works mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') result = h.readlines() self.assertEqual(result, ['foo\n', 'bar\n', 'baz\n']) # Test that files without a final newline will also be correctly # emulated mock = mock_open(read_data='foo\nbar\nbaz') with patch('%s.open' % __name__, mock, create=True): h = open('bar') result = h.readlines() self.assertEqual(result, ['foo\n', 'bar\n', 'baz']) def test_read_bytes(self): mock = mock_open(read_data=b'\xc6') with patch('%s.open' % __name__, mock, create=True): with open('abc', 'rb') as f: result = f.read() self.assertEqual(result, b'\xc6') def test_readline_bytes(self): m = mock_open(read_data=b'abc\ndef\nghi\n') with patch('%s.open' % __name__, m, create=True): with open('abc', 'rb') as f: line1 = f.readline() line2 = f.readline() line3 = f.readline() self.assertEqual(line1, b'abc\n') self.assertEqual(line2, b'def\n') self.assertEqual(line3, b'ghi\n') def test_readlines_bytes(self): m = mock_open(read_data=b'abc\ndef\nghi\n') with patch('%s.open' % __name__, m, create=True): with open('abc', 'rb') as f: result = f.readlines() self.assertEqual(result, [b'abc\n', b'def\n', b'ghi\n']) def test_mock_open_read_with_argument(self): # At one point calling read with an argument was broken # for mocks returned by mock_open some_data = 'foo\nbar\nbaz' mock = mock_open(read_data=some_data) self.assertEqual(mock().read(10), some_data[:10]) self.assertEqual(mock().read(10), some_data[:10]) f = mock() self.assertEqual(f.read(10), some_data[:10]) self.assertEqual(f.read(10), some_data[10:]) def test_interleaved_reads(self): # Test that calling read, readline, and readlines pulls data # sequentially from the data we preload with mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') line1 = h.readline() rest = h.readlines() self.assertEqual(line1, 'foo\n') self.assertEqual(rest, ['bar\n', 'baz\n']) mock = mock_open(read_data='foo\nbar\nbaz\n') with patch('%s.open' % __name__, mock, create=True): h = open('bar') line1 = h.readline() rest = h.read() self.assertEqual(line1, 'foo\n') self.assertEqual(rest, 'bar\nbaz\n') def test_overriding_return_values(self): mock = mock_open(read_data='foo') handle = mock() handle.read.return_value = 'bar' handle.readline.return_value = 'bar' handle.readlines.return_value = ['bar'] self.assertEqual(handle.read(), 'bar') self.assertEqual(handle.readline(), 'bar') self.assertEqual(handle.readlines(), ['bar']) # call repeatedly to check that a StopIteration is not propagated self.assertEqual(handle.readline(), 'bar') self.assertEqual(handle.readline(), 'bar') if __name__ == '__main__': unittest.main() mock-4.0.3/release.py000066400000000000000000000044151376434722300144600ustar00rootroot00000000000000import re from glob import glob from os.path import join from subprocess import call import blurb as blurb_module from argparse import ArgumentParser from mock import version_info VERSION_TYPES = ['major', 'minor', 'bugfix'] def incremented_version(version_info, type_): type_index = VERSION_TYPES.index(type_) version_info = tuple(0 if i>type_index else (e+(1 if i==type_index else 0)) for i, e in enumerate(version_info)) return '.'.join(str(p) for p in version_info) def text_from_news(): # hack: blurb_module.sections.append('NEWS.d') blurbs = blurb_module.Blurbs() for path in glob(join('NEWS.d', '*')): blurbs.load_next(path) text = [] for metadata, body in blurbs: bpo = metadata['bpo'] body = f"- Issue #{bpo}: " + body text.append(blurb_module.textwrap_body(body, subsequent_indent=' ')) return '\n'.join(text) def news_to_changelog(version): with open('CHANGELOG.rst') as source: current_changelog = source.read() text = [version] text.append('-'*len(version)) text.append('') text.append(text_from_news()) text.append(current_changelog) new_changelog = '\n'.join(text) with open('CHANGELOG.rst', 'w') as target: target.write(new_changelog) def update_version(new_version): path = join('mock', '__init__.py') with open(path) as source: text = source.read() text = re.sub("(__version__ = ')[^']+(')", r"\g<1>"+new_version+r"\2", text) with open(path, 'w') as target: target.write(text) def git(command): return call('git '+command, shell=True) def git_commit(new_version): git('rm NEWS.d/*') git('add CHANGELOG.rst') git('add mock/__init__.py') git(f'commit -m "Preparing for {new_version} release."') def parse_args(): parser = ArgumentParser() parser.add_argument('type', choices=VERSION_TYPES) return parser.parse_args() def main(): args = parse_args() new_version = incremented_version(version_info, args.type) news_to_changelog(new_version) update_version(new_version) git_commit(new_version) print(f'{new_version} ready to push, please check the HEAD commit first!') if __name__ == '__main__': main() mock-4.0.3/setup.cfg000066400000000000000000000023271376434722300143070ustar00rootroot00000000000000[metadata] name = mock summary = Rolling backport of unittest.mock for all Pythons home-page = http://mock.readthedocs.org/en/latest/ description-file = README.rst author = Testing Cabal author-email = testing-in-python@lists.idyll.org classifiers = Development Status :: 5 - Production/Stable Environment :: Console Intended Audience :: Developers License :: OSI Approved :: BSD License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Topic :: Software Development :: Libraries Topic :: Software Development :: Libraries :: Python Modules Topic :: Software Development :: Testing keyword = testing, test, mock, mocking, unittest, patching, stubs, fakes, doubles [options] python_requires=>=3.6 packages = mock [options.extras_require] docs = sphinx test = pytest<5.4 pytest-cov build = twine wheel blurb [tool:pytest] python_files=test*.py filterwarnings = error::RuntimeWarning ignore::DeprecationWarning mock-4.0.3/setup.py000077500000000000000000000003661376434722300142040ustar00rootroot00000000000000import re from os.path import join import setuptools setuptools.setup( version=re.search("__version__ = '([^']+)'", open(join('mock', '__init__.py')).read()).group(1), long_description=open('README.rst').read(), ) mock-4.0.3/tox.ini000066400000000000000000000002651376434722300140000ustar00rootroot00000000000000[tox] envlist = py36,py37,py38,docs [testenv] commands = {envbindir}/pytest {posargs} [testenv:docs] deps = sphinx commands = {envbindir}/python setup.py build_sphinx