Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-mockito for openSUSE:Factory checked in at 2022-09-30 17:57:41 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-mockito (Old) and /work/SRC/openSUSE:Factory/.python-mockito.new.2275 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-mockito" Fri Sep 30 17:57:41 2022 rev:10 rq:1007057 version:1.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-mockito/python-mockito.changes 2021-04-22 18:04:57.230597364 +0200 +++ /work/SRC/openSUSE:Factory/.python-mockito.new.2275/python-mockito.changes 2022-09-30 17:57:59.457273815 +0200 @@ -1,0 +2,32 @@ +Thu Sep 29 16:37:08 UTC 2022 - Yogalakshmi Arunachalam <[email protected]> + +- Release 1.4.0 (August 25, 2022) + + - @avandierast implemented `thenCallOriginalImplementation`. See #60 + # Let `os.path.exists` use the real filesystem (often needed when + # the testing framework needs itself a working `os.path.exists` + # implementation) *but* fake a `.flake8` file. + when(os.path).exists(...).thenCallOriginalImplementation() + when(os.path).exists('.flake8').thenReturn(True) + +- Release 1.3.5 (August 18, 2022) + - Restore compatibility with Python 2.7 + +- Release 1.3.3 (June 23, 2022) + - Hotfix: Correctly unstub methods extracted to the module level, for example ``random.randint()`` et.al. from the standard library. See #53 + +- Release 1.3.2 (June 23, 2022) + - Let `mock(spec=SomeClass)` work just as `mock(SomeClass)` + +- Release 1.3.1 (June 14, 2022) + - Reimplement `captor` to capture only during execution phase of a test. + +- Release 1.3.0 (December 3, 2021) + - Teach `captor` to remember all used values (@shashankrnr32). E.g. + arg = captor() + mock.do_something(123) + mock.do_something(456) + verify(mock).do_something(arg) + assert arg.all_values == [123, 456] + +------------------------------------------------------------------- Old: ---- 1.2.2.tar.gz New: ---- 1.4.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-mockito.spec ++++++ --- /var/tmp/diff_new_pack.XzHCbx/_old 2022-09-30 17:57:59.817274584 +0200 +++ /var/tmp/diff_new_pack.XzHCbx/_new 2022-09-30 17:57:59.825274602 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-mockito # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python36 1 Name: python-mockito -Version: 1.2.2 +Version: 1.4.0 Release: 0 Summary: Spying framework License: MIT ++++++ 1.2.2.tar.gz -> 1.4.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/.bumpversion.cfg new/mockito-python-1.4.0/.bumpversion.cfg --- old/mockito-python-1.2.2/.bumpversion.cfg 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/.bumpversion.cfg 2022-08-25 22:48:31.000000000 +0200 @@ -1,5 +1,5 @@ [bumpversion] -current_version = 1.2.2 +current_version = 1.4.0 commit = True message = Bump version to {new_version} tag = True @@ -16,4 +16,3 @@ values = dev release - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/.codespellrc new/mockito-python-1.4.0/.codespellrc --- old/mockito-python-1.2.2/.codespellrc 1970-01-01 01:00:00.000000000 +0100 +++ new/mockito-python-1.4.0/.codespellrc 2022-08-25 22:48:31.000000000 +0200 @@ -0,0 +1,3 @@ +[codespell] +skip=./docs/_build,./.mypy_cache,*.sublime-workspace,.git +ignore-words-list=atleast diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/.github/workflows/test-lint-go.yml new/mockito-python-1.4.0/.github/workflows/test-lint-go.yml --- old/mockito-python-1.2.2/.github/workflows/test-lint-go.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/mockito-python-1.4.0/.github/workflows/test-lint-go.yml 2022-08-25 22:48:31.000000000 +0200 @@ -0,0 +1,105 @@ +name: Run tests and lint, maybe deploy + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: + - '2.7' + - '3.5' + - '3.6' + - '3.7' + - '3.8' + - '3.9' + - '3.10' + - '3.11-dev' + name: Run tests on Python ${{ matrix.python-version }} + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pytest numpy + - name: Run pytest + run: pytest + + lint: + runs-on: ubuntu-latest + name: Lint with flake8 + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install flake8 + - name: Run flake8 + run: flake8 . + + spellcheck: + runs-on: ubuntu-latest + name: Spellcheck with codespell + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install codespell + - name: Run codespell + run: codespell + + type-check: + runs-on: ubuntu-latest + name: Check with mypy + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install mypy + - name: Run mypy + run: mypy mockito + + deploy: + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + needs: [test, lint, type-check] + runs-on: ubuntu-latest + name: Deploy to pypi + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.10' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: python -m build + - name: Publish package + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} + verbose: true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/.gitignore new/mockito-python-1.4.0/.gitignore --- old/mockito-python-1.2.2/.gitignore 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/.gitignore 2022-08-25 22:48:31.000000000 +0200 @@ -1,6 +1,7 @@ *.pyc -build +build/ +dist/ docs/_build .eggs/ .pytest_cache -__pycache__ \ No newline at end of file +__pycache__ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/.travis.yml new/mockito-python-1.4.0/.travis.yml --- old/mockito-python-1.2.2/.travis.yml 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/.travis.yml 1970-01-01 01:00:00.000000000 +0100 @@ -1,25 +0,0 @@ -language: python -python: -- '2.7' -- '3.4' -- '3.5' -- '3.6' -- '3.7' -- '3.8' -install: - - if [[ $TRAVIS_PYTHON_VERSION == 3.8 ]]; then pip install flake8; fi - - pip install . -script: - - if [[ $TRAVIS_PYTHON_VERSION == 3.8 ]]; then flake8 .; fi - - py.test -deploy: - provider: pypi - user: herrkaste - password: - secure: ou5t21x3ysjuRA4oj0oEJIiwffkrsKMoyBL0AhBc+Qq7bxFIEMCdTgfkh1lrWrhGA0xNIAwDHOL9gJrpYaqeLUx6F0mCQc2zRfNzYNf/t4x0+23WsIGQ1HxWGCW9ixLmtXU+zFGK6pUoLZjPdCT0HjZsAjgKOudTv4M1+BlUhFnmAvdmBKjl3jfNY4h5JWbVrhPg6HzMgfNI+vQ7JIFjHZ4a0i2BqEbTMt/2UZGal+Mau0sEO3/y4Ud0LcTRhtA6VA0J7nEcv85q+/JhqmbXTs9h6Bz1KC3V4nMPaaIpGqhrX20eLI6fxULlB/yuBq5jNXSvDMeH9lRyv5AlDUy9NAh++JciXSYYp3p984V/LEwRKM3VyB+ZUUe+KeLN7rk6d/Q2elFW9IHpw9cSsmbl1zrG4GjP+eCpCOw0lrLO6MAijSCGXEzWN+5ViwMDrGCS/6CjRRUBRxcXBebeo6ZB6Wkw+JWdFLW3s/OMzDeVtOEkuP6qdR7VMNn2uYOkPbiDZO4d5UGS09gGMWYasqxP/QJth2yuF95uQmqOhLuGSzI02YS6+L1/Xh2fEmsD8LFF3ATfA0MZ/phHjjvD/ZUmnVgGczW9p1zEohJ9EDQsV4P2fHzNP6nblcx7iBTzKsEsqcjTpOn7UYhFAsyiga17dhcfa5IU2nSb0JzzIeWdM0Q= - on: - tags: true - python: 3.8 - branch: master - distributions: sdist bdist_wheel - repo: kaste/mockito-python diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/CHANGES.txt new/mockito-python-1.4.0/CHANGES.txt --- old/mockito-python-1.2.2/CHANGES.txt 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/CHANGES.txt 2022-08-25 22:48:31.000000000 +0200 @@ -1,6 +1,59 @@ MOCKITO CHANGE LOG ================== +Release 1.4.0 (August 25, 2022) +------------------------------- + +- @avandierast implemented `thenCallOriginalImplementation`. See #60 + +:: + + # Let `os.path.exists` use the real filesystem (often needed when + # the testing framework needs itself a working `os.path.exists` + # implementation) *but* fake a `.flake8` file. + when(os.path).exists(...).thenCallOriginalImplementation() + when(os.path).exists('.flake8').thenReturn(True) + + + +Release 1.3.5 (August 18, 2022) +------------------------------- + +- Restore compatibility with Python 2.7 + + +Release 1.3.3 (June 23, 2022) +----------------------------- + +- Hotfix: Correctly unstub methods extracted to the module level, for example ``random.randint()`` et.al. from the standard library. See #53 + + +Release 1.3.2 (June 23, 2022) +----------------------------- + +- Let `mock(spec=SomeClass)` work just as `mock(SomeClass)` + + +Release 1.3.1 (June 14, 2022) +----------------------------- + +- Reimplement `captor` to capture only during execution phase of a test. + + +Release 1.3.0 (December 3, 2021) +-------------------------------- + +- Teach `captor` to remember all used values (@shashankrnr32). E.g. + +:: + + arg = captor() + mock.do_something(123) + mock.do_something(456) + verify(mock).do_something(arg) + assert arg.all_values == [123, 456] + + Release 1.2.2 (September 9, 2020) --------------------------------- @@ -21,8 +74,10 @@ - @felixonmars fixed a small compatibility issue with python 3.8 - Mocking properties has become a bit easier. (#26) E.g. +:: + prop = mock() - when(m).__get__(...).thenReturn(23) + when(prop).__get__(...).thenReturn(23) m = mock({'name': prop}) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/docs/nutshell.rst new/mockito-python-1.4.0/docs/nutshell.rst --- old/mockito-python-1.2.2/docs/nutshell.rst 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/docs/nutshell.rst 2022-08-25 22:48:31.000000000 +0200 @@ -41,15 +41,14 @@ >>> when(os.path).exist('./somewhat').thenReturn(True) Traceback (most recent call last): <...> - mockito.invocation.InvocationError: You tried to stub a method 'exist' the objec - t (<module 'ntpath' from ...>) doesn't have. + mockito.invocation.InvocationError: You tried to stub a method 'exist' + the object (<module 'ntpath' from ...>) doesn't have. If that's too strict, you can change it :: - >>> when(os.path, strict=False).exist('another_place').thenReturn('well, nice he - re') + >>> when(os.path, strict=False).exist('another_place').thenReturn('well, nice here') <mockito.invocation.AnswerSelector object at 0x00D429B0> >>> os.path.exist('another_place') 'well, nice here' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/docs/walk-through.rst new/mockito-python-1.4.0/docs/walk-through.rst --- old/mockito-python-1.2.2/docs/walk-through.rst 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/docs/walk-through.rst 2022-08-25 22:48:31.000000000 +0200 @@ -19,6 +19,7 @@ # now, obviously, you get the same answer, regardless of the arguments os.path.exists('FooBar') # => True + os.path.exists('BarFoo') # => True You can combine both stubs. E.g. nothing exists, except one file:: @@ -31,6 +32,21 @@ spy2(os.path.exists) when(os.path).exists('.flake8').thenReturn(False) +Another way to write the same thing is:: + + when(os.path).exists(...).thenCallOriginalImplementation() + when(os.path).exists('.flake8').thenReturn(False) + +And actually `spy2` uses `thenCallOriginalImplementation` under the hood. Why spying at all: either you want the implementation *almost* intact as above or you +need the implementation to stay intact but want to `verify` its usage. E.g.:: + + spy2(os.path.exists) + # now do some stuff + do_stuff() + # then verify the we asked for the cache exactly once + verify(os.path, times=1).exists("cache/.foo") + + When patching, you **MUST** **not** forget to :func:`unstub` of course! You can do this explicitly :: @@ -41,6 +57,7 @@ Usually you do this unconditionally in your `teardown` function. If you're using `pytest`, you could define a fixture instead :: + # conftest.py import pytest @@ -193,7 +210,7 @@ verify(obj).say('Hi') # by default all invoked methods take any arguments and return None - # you can configure your expected method calls with the ususal `when` + # you can configure your expected method calls with the usual `when` when(obj).say('Hi').thenReturn('Ho') # There is also a shortcut to set some attributes diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/__init__.py new/mockito-python-1.4.0/mockito/__init__.py --- old/mockito-python-1.2.2/mockito/__init__.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/__init__.py 2022-08-25 22:48:31.000000000 +0200 @@ -44,7 +44,7 @@ from .matchers import any, contains, times from .verification import never -__version__ = '1.2.2' +__version__ = '1.4.0' __all__ = [ 'mock', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/invocation.py new/mockito-python-1.4.0/mockito/invocation.py --- old/mockito-python-1.2.2/mockito/invocation.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/invocation.py 2022-08-25 22:48:31.000000000 +0200 @@ -18,19 +18,26 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from . import matchers +import functools +import inspect import operator -from . import signature +from collections import deque + +from . import matchers, signature from . import verification as verificationModule from .utils import contains_strict -from collections import deque -import functools +MYPY = False +if MYPY: + from typing import Any, Callable, Deque, Dict, Tuple class InvocationError(AttributeError): pass +class AnswerError(AttributeError): + pass + __tracebackhide__ = operator.methodcaller( "errisinstance", @@ -44,8 +51,8 @@ self.method_name = method_name self.strict = mock.strict - self.params = () - self.named_params = {} + self.params = () # type: Tuple[Any, ...] + self.named_params = {} # type: Dict[str, Any] def _remember_params(self, params, named_params): self.params = params @@ -81,17 +88,22 @@ signature.match_signature(sig, args, kwargs) def __call__(self, *params, **named_params): + if self.mock.eat_self(self.method_name): + params_without_first_arg = params[1:] + else: + params_without_first_arg = params if self.strict: self.ensure_mocked_object_has_method(self.method_name) self.ensure_signature_matches( - self.method_name, params, named_params) + self.method_name, params_without_first_arg, named_params) - self._remember_params(params, named_params) + self._remember_params(params_without_first_arg, named_params) self.mock.remember(self) for matching_invocation in self.mock.stubbed_invocations: if matching_invocation.matches(self): matching_invocation.should_answer(self) + matching_invocation.capture_arguments(self) return matching_invocation.answer_first( *params, **named_params) @@ -156,6 +168,26 @@ return False return True + def capture_arguments(self, invocation): + for x, p1 in enumerate(self.params): + if isinstance(p1, matchers.Capturing): + try: + p2 = invocation.params[x] + except IndexError: + continue + + p1.capture_value(p2) + + for key, p1 in self.named_params.items(): + if isinstance(p1, matchers.Capturing): + try: + p2 = invocation.named_params[key] + except KeyError: + continue + + p1.capture_value(p2) + + def _remember_params(self, params, named_params): if ( contains_strict(params, Ellipsis) @@ -237,6 +269,7 @@ matched_invocations = [] for invocation in self.mock.invocations: if self.matches(invocation): + self.capture_arguments(invocation) matched_invocations.append(invocation) self.verification.verify(self, len(matched_invocations)) @@ -383,23 +416,60 @@ raise exception +def discard_self(function): + def function_without_self(*args, **kwargs): + args = args[1:] + return function(*args, **kwargs) + + return function_without_self + + class AnswerSelector(object): def __init__(self, invocation): self.invocation = invocation + self.discard_first_arg = \ + invocation.mock.eat_self(invocation.method_name) def thenReturn(self, *return_values): for return_value in return_values: - self.__then(functools.partial(return_, return_value)) + answer = functools.partial(return_, return_value) + self.__then(answer) return self def thenRaise(self, *exceptions): for exception in exceptions: - self.__then(functools.partial(raise_, exception)) + answer = functools.partial(raise_, exception) + self.__then(answer) return self def thenAnswer(self, *callables): for callable in callables: - self.__then(callable) + answer = callable + if self.discard_first_arg: + answer = discard_self(answer) + self.__then(answer) + return self + + def thenCallOriginalImplementation(self): + answer = self.invocation.mock.get_original_method( + self.invocation.method_name + ) + if not answer: + raise AnswerError( + "'%s' has no original implementation for '%s'." % + (self.invocation.mock.mocked_obj, self.invocation.method_name) + ) + if ( + # A classmethod is not callable + # and a staticmethod is not callable in old version of python, + # so we get the underlying function. + isinstance(answer, classmethod) or isinstance(answer, staticmethod) + # If the method is bound, we unbind it. + or inspect.ismethod(answer) + ): + answer = answer.__func__ + + self.__then(answer) return self def __then(self, answer): @@ -415,7 +485,7 @@ class CompositeAnswer(object): def __init__(self): #: Container for answers, which are just ordinary callables - self.answers = deque() + self.answers = deque() # type: Deque[Callable] #: Counter for the maximum answers we ever had self.answer_count = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/matchers.py new/mockito-python-1.4.0/mockito/matchers.py --- old/mockito-python-1.2.2/mockito/matchers.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/matchers.py 2022-08-25 22:48:31.000000000 +0200 @@ -60,7 +60,7 @@ """ import re - +builtin_any = any __all__ = [ 'and_', 'or_', 'not_', @@ -77,6 +77,7 @@ 'kwargs', 'KWARGS' ] + class _ArgsSentinel(object): def __repr__(self): return '*args' @@ -106,10 +107,21 @@ # """ + +class MatcherError(RuntimeError): + '''Indicates generic runtime error raised by mockito-python matchers + ''' + pass + + class Matcher: def matches(self, arg): pass +class Capturing: + def capture_value(self, value): + pass + class Any(Matcher): def __init__(self, wanted_type=None): @@ -183,9 +195,7 @@ for matcher in matchers] def matches(self, arg): - return __builtins__['any']( - [matcher.matches(arg) for matcher in self.matchers] - ) + return builtin_any([matcher.matches(arg) for matcher in self.matchers]) def __repr__(self): return "<Or: %s>" % self.matchers @@ -243,21 +253,29 @@ return "<Matches: %s>" % self.regex.pattern -class ArgumentCaptor(Matcher): +class ArgumentCaptor(Matcher, Capturing): def __init__(self, matcher=None): self.matcher = matcher or Any() - self.value = None + self.all_values = [] def matches(self, arg): result = self.matcher.matches(arg) if not result: return - self.value = arg return True + @property + def value(self): + if not self.all_values: + raise MatcherError("No argument value was captured!") + return self.all_values[-1] + + def capture_value(self, value): + self.all_values.append(value) + def __repr__(self): - return "<ArgumentCaptor: matcher=%s value=%s>" % ( - repr(self.matcher), self.value, + return "<ArgumentCaptor: matcher=%s values=%s>" % ( + repr(self.matcher), self.all_values, ) @@ -370,14 +388,22 @@ def captor(matcher=None): - """Returns argument captor that captures value for further assertions + """Returns argument captor that captures values for further assertions Example:: - arg_captor = captor(any(int)) - when(mock).do_something(arg_captor) + arg = captor() mock.do_something(123) - assert arg_captor.value == 123 + mock.do_something(456) + verify(mock).do_something(arg) + assert arg.value == 456 + assert arg.all_values == [123, 456] + + You can restrict what the captor captures using the other matchers + shown herein:: + + arg = captor(any(str)) + arg = captor(contains("foo")) """ return ArgumentCaptor(matcher) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/mocking.py new/mockito-python-1.4.0/mockito/mocking.py --- old/mockito-python-1.2.2/mockito/mocking.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/mocking.py 2022-08-25 22:48:31.000000000 +0200 @@ -33,6 +33,13 @@ invocation.InvocationError ) +MYPY = False +if MYPY: + from typing import Deque, List, Union + RealInvocation = Union[ + invocation.RememberedInvocation, + invocation.RememberedProxyInvocation + ] class _Dummy(object): @@ -40,7 +47,7 @@ # must be configured before use, but we want `mock`s to be callable by # default. def __call__(self, *args, **kwargs): - return self.__getattr__('__call__')(*args, **kwargs) + return self.__getattr__('__call__')(*args, **kwargs) # type: ignore[attr-defined] # noqa: E501 def remembered_invocation_builder(mock, method_name, *args, **kwargs): @@ -54,24 +61,29 @@ self.strict = strict self.spec = spec - self.invocations = deque() - self.stubbed_invocations = deque() + self.invocations = [] # type: List[RealInvocation] + self.stubbed_invocations = deque() \ + # type: Deque[invocation.StubbedInvocation] - self.original_methods = {} + self._original_methods = {} + self._methods_to_unstub = {} self._signatures_store = {} def remember(self, invocation): - self.invocations.appendleft(invocation) + self.invocations.append(invocation) def finish_stubbing(self, stubbed_invocation): self.stubbed_invocations.appendleft(stubbed_invocation) def clear_invocations(self): - self.invocations = deque() + self.invocations = [] + + def get_original_method(self, method_name): + return self._original_methods.get(method_name, None) # STUBBING - def get_original_method(self, method_name): + def _get_original_method_before_stub(self, method_name): """ Looks up the original method on the `spec` object and returns it together with an indication of whether the method is found @@ -97,21 +109,13 @@ def replace_method(self, method_name, original_method): def new_mocked_method(*args, **kwargs): - # we throw away the first argument, if it's either self or cls - if ( - inspect.ismethod(new_mocked_method) - or inspect.isclass(self.mocked_obj) - and not isinstance(new_mocked_method, staticmethod) - ): - args = args[1:] - return remembered_invocation_builder( self, method_name, *args, **kwargs) new_mocked_method.__name__ = method_name if original_method: new_mocked_method.__doc__ = original_method.__doc__ - new_mocked_method.__wrapped__ = original_method + new_mocked_method.__wrapped__ = original_method # type: ignore[attr-defined] # noqa: E501 try: new_mocked_method.__module__ = original_method.__module__ except AttributeError: @@ -123,30 +127,33 @@ ) if isinstance(original_method, staticmethod): - new_mocked_method = staticmethod(new_mocked_method) + new_mocked_method = staticmethod(new_mocked_method) # type: ignore[assignment] # noqa: E501 elif isinstance(original_method, classmethod): - new_mocked_method = classmethod(new_mocked_method) + new_mocked_method = classmethod(new_mocked_method) # type: ignore[assignment] # noqa: E501 elif ( inspect.isclass(self.mocked_obj) and inspect.isclass(original_method) # TBC: Inner classes ): - new_mocked_method = staticmethod(new_mocked_method) + new_mocked_method = staticmethod(new_mocked_method) # type: ignore[assignment] # noqa: E501 self.set_method(method_name, new_mocked_method) def stub(self, method_name): try: - self.original_methods[method_name] + self._methods_to_unstub[method_name] except KeyError: - original_method, was_in_spec = self.get_original_method( - method_name) + ( + original_method, + was_in_spec + ) = self._get_original_method_before_stub(method_name) if was_in_spec: # This indicates the original method was found directly on # the spec object and should therefore be restored by unstub - self.original_methods[method_name] = original_method + self._methods_to_unstub[method_name] = original_method else: - self.original_methods[method_name] = None + self._methods_to_unstub[method_name] = None + self._original_methods[method_name] = original_method self.replace_method(method_name, original_method) def forget_stubbed_invocation(self, invocation): @@ -162,27 +169,25 @@ inv.method_name == invocation.method_name for inv in self.stubbed_invocations ): - original_method = self.original_methods.pop(invocation.method_name) + original_method = self._methods_to_unstub.pop( + invocation.method_name + ) self.restore_method(invocation.method_name, original_method) def restore_method(self, method_name, original_method): # If original_method is None, we *added* it to mocked_obj, so we # must delete it here. - # If we mocked an instance, our mocked function will actually hide - # the one on its class, so we delete as well. - if ( - not original_method - or not inspect.isclass(self.mocked_obj) - and inspect.ismethod(original_method) - ): - delattr(self.mocked_obj, method_name) - else: + if original_method: self.set_method(method_name, original_method) + else: + delattr(self.mocked_obj, method_name) def unstub(self): - while self.original_methods: - method_name, original_method = self.original_methods.popitem() + while self._methods_to_unstub: + method_name, original_method = self._methods_to_unstub.popitem() self.restore_method(method_name, original_method) + self.stubbed_invocations = deque() + self.invocations = [] # SPECCING @@ -203,6 +208,25 @@ self._signatures_store[method_name] = sig return sig + def eat_self(self, method_name): + """Returns if the method will have a prepended self/class arg on call + """ + try: + original_method = self._original_methods[method_name] + except KeyError: + return False + else: + # If original_method is None, we *added* it to mocked_obj + # and thus, it will eat self iff mocked_obj is a class. + return ( + inspect.ismethod(original_method) + or ( + inspect.isclass(self.mocked_obj) + and not isinstance(original_method, staticmethod) + and not inspect.isclass(original_method) + ) + ) + class _OMITTED(object): def __repr__(self): @@ -257,10 +281,9 @@ """ if type(config_or_spec) is dict: - config = config_or_spec + config, spec = config_or_spec, spec else: - config = {} - spec = config_or_spec + config, spec = {}, spec or config_or_spec if strict is OMITTED: strict = False if spec is None else True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/mockito.py new/mockito-python-1.4.0/mockito/mockito.py --- old/mockito-python-1.2.2/mockito/mockito.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/mockito.py 2022-08-25 22:48:31.000000000 +0200 @@ -164,7 +164,7 @@ when(<obj>).<method_name>(<args>).thenReturn(<value>) Compared to simple *patching*, stubbing in mockito requires you to specify - conrete `args` for which the stub will answer with a concrete `<value>`. + concrete `args` for which the stub will answer with a concrete `<value>`. All invocations that do not match this specific call signature will be rejected. They usually throw at call time. @@ -238,7 +238,8 @@ more documentation. Returns `AnswerSelector` interface which exposes `thenReturn`, - `thenRaise`, and `thenAnswer` as usual. Always `strict`. + `thenRaise`, `thenAnswer`, and `thenCallOriginalImplementation` as usual. + Always `strict`. Usage:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/signature.py new/mockito-python-1.4.0/mockito/signature.py --- old/mockito-python-1.2.2/mockito/signature.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/signature.py 2022-08-25 22:48:31.000000000 +0200 @@ -10,7 +10,7 @@ try: from inspect import signature, Parameter except ImportError: - from funcsigs import signature, Parameter + from funcsigs import signature, Parameter # type: ignore[import, no-redef] PY3 = sys.version_info >= (3,) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/spying.py new/mockito-python-1.4.0/mockito/spying.py --- old/mockito-python-1.2.2/mockito/spying.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/spying.py 2022-08-25 22:48:31.000000000 +0200 @@ -25,7 +25,6 @@ from .mockito import when2 from .invocation import RememberedProxyInvocation from .mocking import Mock, _Dummy, mock_registry -from .utils import get_obj __all__ = ['spy'] @@ -96,10 +95,4 @@ """ - if isinstance(fn, str): - answer = get_obj(fn) - else: - answer = fn - - when2(fn, Ellipsis).thenAnswer(answer) - + when2(fn, Ellipsis).thenCallOriginalImplementation() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/utils.py new/mockito-python-1.4.0/mockito/utils.py --- old/mockito-python-1.2.2/mockito/utils.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/utils.py 2022-08-25 22:48:31.000000000 +0200 @@ -77,7 +77,7 @@ if frame_info[3] in ('patch', 'spy2'): continue - source = ''.join(frame_info[4]) + source = ''.join(frame_info[4] or []) m = FIND_ID.match(source) if m: # id should be something like `os.path.exists` etc. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/mockito/verification.py new/mockito-python-1.4.0/mockito/verification.py --- old/mockito-python-1.2.2/mockito/verification.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/mockito/verification.py 2022-08-25 22:48:31.000000000 +0200 @@ -22,6 +22,7 @@ __all__ = ['never', 'VerificationError'] + class VerificationError(AssertionError): '''Indicates error during verification of invocations. @@ -104,7 +105,7 @@ % ( invocation, "\n ".join( - str(invoc) for invoc in reversed(invocations) + str(invoc) for invoc in invocations ) ) ) @@ -130,13 +131,13 @@ def __init__(self, original_verification): ''' - @param original_verification: Original verifiaction to degrade to if + @param original_verification: Original verification to degrade to if order of invocation was ok. ''' self.original_verification = original_verification def verify(self, wanted_invocation, count): - for invocation in reversed(wanted_invocation.mock.invocations): + for invocation in wanted_invocation.mock.invocations: if not invocation.verified_inorder: if not wanted_invocation.matches(invocation): raise VerificationError( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/pytest.ini new/mockito-python-1.4.0/pytest.ini --- old/mockito-python-1.2.2/pytest.ini 1970-01-01 01:00:00.000000000 +0100 +++ new/mockito-python-1.4.0/pytest.ini 2022-08-25 22:48:31.000000000 +0200 @@ -0,0 +1,3 @@ +[pytest] +asyncio_mode=auto +xfail_strict=true diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/setup.py new/mockito-python-1.4.0/setup.py --- old/mockito-python-1.2.2/setup.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/setup.py 2022-08-25 22:48:31.000000000 +0200 @@ -24,6 +24,7 @@ description='Spying framework', long_description=open('README.rst').read(), install_requires=install_requires, + python_requires='>=2.7', classifiers=[ 'Development Status :: 4 - Beta', 'Intended Audience :: Developers', @@ -32,9 +33,10 @@ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + 'Programming Language :: Python :: 3.10', ]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/call_original_implem_test.py new/mockito-python-1.4.0/tests/call_original_implem_test.py --- old/mockito-python-1.2.2/tests/call_original_implem_test.py 1970-01-01 01:00:00.000000000 +0100 +++ new/mockito-python-1.4.0/tests/call_original_implem_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -0,0 +1,89 @@ + +import sys + +import pytest +from mockito import mock, when +from mockito.invocation import AnswerError + +from . import module +from .test_base import TestBase + + +class Dog: + def __init__(self, huge=False): + self.huge = huge + + def bark(self): + if self.huge: + return "woof" + else: + return "waf ! waf ! waf ! waf ! waf ! waf !" + + @classmethod + def class_bark(cls): + return cls.__name__ + " woof" + + @staticmethod + def static_bark(arg): + return str(arg) + " woof" + + +class CallOriginalImplementationTest(TestBase): + + def testClassMethod(self): + when(Dog).class_bark().thenCallOriginalImplementation() + + self.assertEqual("Dog woof", Dog.class_bark()) + + def testStaticMethod(self): + when(Dog).static_bark("wif").thenCallOriginalImplementation() + self.assertEqual("wif woof", Dog.static_bark("wif")) + + def testStaticMethodOnInstance(self): + dog = Dog() + when(Dog).static_bark("wif").thenCallOriginalImplementation() + self.assertEqual("wif woof", dog.static_bark("wif")) + + def testMethod(self): + when(Dog).bark().thenCallOriginalImplementation() + + assert Dog(huge=True).bark() == "woof" + + def testMethodOnInstance(self): + dog = Dog(huge=True) + when(dog).bark().thenCallOriginalImplementation() + + assert dog.bark() == "woof" + + def testFunction(self): + when(module).one_arg(Ellipsis).thenCallOriginalImplementation() + assert module.one_arg("woof") == "woof" + + def testChain(self): + when(module).one_arg(Ellipsis) \ + .thenReturn("wif") \ + .thenCallOriginalImplementation() \ + .thenReturn("waf") + assert module.one_arg("woof") == "wif" + assert module.one_arg("woof") == "woof" + assert module.one_arg("woof") == "waf" + + def testDumbMockHasNoOriginalImplementations(self): + dog = mock() + answer_selector = when(dog).bark() + with pytest.raises(AnswerError) as exc: + answer_selector.thenCallOriginalImplementation() + + if sys.version_info >= (3, 0): + class_str_value = "mockito.mocking.mock.<locals>.Dummy" + else: + class_str_value = "mockito.mocking.Dummy" + assert str(exc.value) == ( + "'<class '%s'>' " + "has no original implementation for 'bark'." + ) % class_str_value + + def testSpeccedMockHasOriginalImplementations(self): + dog = mock({"huge": True}, spec=Dog) + when(dog).bark().thenCallOriginalImplementation() + assert dog.bark() == "woof" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/ellipsis_test.py new/mockito-python-1.4.0/tests/ellipsis_test.py --- old/mockito-python-1.2.2/tests/ellipsis_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/ellipsis_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -1,9 +1,8 @@ -import pytest - from collections import namedtuple -from mockito import when, args, kwargs, invocation, mock +import pytest +from mockito import args, invocation, kwargs, mock, when class Dog(object): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/instancemethods_test.py new/mockito-python-1.4.0/tests/instancemethods_test.py --- old/mockito-python-1.2.2/tests/instancemethods_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/instancemethods_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -73,6 +73,14 @@ unstub() assert rex.waggle() == 'Wuff!' + def testPartialUnstubShowsTheMockedClass(self): + when(Dog).waggle().thenReturn('Nope!') + + rex = Dog() + when(rex).waggle().thenReturn('Sure!') + unstub(rex) + + assert rex.waggle() == 'Nope!' def testStubAnInstanceMethod(self): when(Dog).waggle().thenReturn('Boing!') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/matchers_test.py new/mockito-python-1.4.0/tests/matchers_test.py --- old/mockito-python-1.2.2/tests/matchers_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/matchers_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -17,9 +17,9 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. - +from mockito.matchers import MatcherError from .test_base import TestBase -from mockito import mock, verify +from mockito import mock, verify, when from mockito.matchers import and_, or_, not_, eq, neq, lt, lte, gt, gte, \ any_, arg_that, contains, matches, captor, ANY, ARGS, KWARGS import re @@ -208,33 +208,91 @@ class ArgumentCaptorTest(TestBase): - def testShouldSatisfyIfInnerMatcherIsSatisfied(self): - c = captor(contains("foo")) - self.assertTrue(c.matches("foobar")) - - def testShouldNotSatisfyIfInnerMatcherIsNotSatisfied(self): - c = captor(contains("foo")) - self.assertFalse(c.matches("barbam")) - - def testShouldReturnNoneValueByDefault(self): - c = captor(contains("foo")) - self.assertEqual(None, c.value) - - def testShouldReturnNoneValueIfDidntMatch(self): - c = captor(contains("foo")) - c.matches("bar") - self.assertEqual(None, c.value) - - def testShouldReturnLastMatchedValue(self): - c = captor(contains("foo")) - c.matches("foobar") - c.matches("foobam") - c.matches("bambaz") - self.assertEqual("foobam", c.value) - - def testShouldDefaultMatcherToAny(self): - c = captor() - c.matches("foo") - c.matches(123) - self.assertEqual(123, c.value) + def test_matches_anything_by_default(self): + assert captor().matches(12) + assert captor().matches("anything") + assert captor().matches(int) + + def test_matches_is_constrained_by_inner_matcher(self): + assert captor(any_(int)).matches(12) + assert not captor(any_(int)).matches("12") + + def test_all_values_initially_is_empty(self): + c = captor() + assert c.all_values == [] + + def test_captures_all_values(self): + m = mock() + c = captor() + + when(m).do(c) + m.do("any") + m.do("thing") + + assert c.all_values == ["any", "thing"] + + def test_captures_only_matching_values(self): + m = mock() + c = captor(any_(int)) + + when(m).do(c) + m.do("any") + m.do("thing") + m.do(21) + + assert c.all_values == [21] + + def test_captures_all_values_while_verifying(self): + m = mock() + c = captor() + + m.do("any") + m.do("thing") + verify(m, times=2).do(c) + + assert c.all_values == ["any", "thing"] + + def test_remember_last_value(self): + m = mock() + c = captor() + + when(m).do(c) + m.do("any") + m.do("thing") + + assert c.value == "thing" + + def test_remember_last_value_while_verifying(self): + m = mock() + c = captor() + + m.do("any") + m.do("thing") + verify(m, times=2).do(c) + + assert c.value == "thing" + + def test_accessing_value_throws_if_nothing_captured_yet(self): + c = captor() + with self.assertRaises(MatcherError): + _ = c.value + + def test_expose_issue_49_using_when(self): + m = mock() + c = captor() + + when(m).do(c, 10) + when(m).do(c, 11) + m.do("anything", 10) + + assert c.all_values == ["anything"] + + def test_expose_issue_49_using_verify(self): + m = mock() + c = captor() + + m.do("anything", 10) + verify(m).do(c, 10) + verify(m, times=0).do(c, 11) + assert c.all_values == ["anything"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/modulefunctions_test.py new/mockito-python-1.4.0/tests/modulefunctions_test.py --- old/mockito-python-1.2.2/tests/modulefunctions_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/modulefunctions_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -20,11 +20,12 @@ import os -from .test_base import TestBase -from mockito import when, unstub, verify, any +from mockito import any, unstub, verify, when from mockito.invocation import InvocationError from mockito.verification import VerificationError +from .test_base import TestBase + class ModuleFunctionsTest(TestBase): def tearDown(self): @@ -98,3 +99,15 @@ from . import module when(module).Foo().thenReturn('mocked') assert module.Foo() == 'mocked' + + def testUnstubFunctionOnModuleWhichIsActuallyAMethod_issue_53(self): + import random + when(random).randint(Ellipsis).thenReturn("mocked") + assert random.randint(1, 10) == "mocked" + unstub(random) + assert random.randint(1, 10) != "mocked" + + def testAddFakeMethodInNotStrictMode(self): + when(os.path, strict=False).new_exists("test").thenReturn(True) + + self.assertEqual(True, os.path.new_exists("test")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/signatures_test.py new/mockito-python-1.4.0/tests/signatures_test.py --- old/mockito-python-1.2.2/tests/signatures_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/signatures_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -8,7 +8,7 @@ class CallSignature(namedtuple('CallSignature', 'args kwargs')): def raises(self, reason): - return pytest.mark.xfail(self, raises=reason, strict=True) + return pytest.mark.xfail(str(self), raises=reason, strict=True) def sig(*a, **kw): return CallSignature(a, kw) @@ -450,7 +450,7 @@ try: import builtins except ImportError: - import __builtin__ as builtins + import __builtin__ as builtins # type: ignore[import, no-redef] # noqa: E501 try: when(builtins).open('foo') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/speccing_test.py new/mockito-python-1.4.0/tests/speccing_test.py --- old/mockito-python-1.2.2/tests/speccing_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/speccing_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -102,6 +102,21 @@ assert isinstance(action, Action) + def testShouldPassIsInstanceChecks_2(self): + action = mock(spec=Action) + + assert isinstance(action, Action) + + def testShouldPassIsInstanceChecks_3(self): + action = mock({}, Action) + + assert isinstance(action, Action) + + def testShouldPassIsInstanceChecks_4(self): + action = mock({}, spec=Action) + + assert isinstance(action, Action) + def testHasANiceName(self): action = mock(Action) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/spying_test.py new/mockito-python-1.4.0/tests/spying_test.py --- old/mockito-python-1.2.2/tests/spying_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/spying_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -154,3 +154,7 @@ assert dummy.return_args('box') == 'foo' assert dummy.return_args('fox') == 'fix' + def testSpyOnClass(self): + spy2(Dummy.foo) + assert Dummy().foo() == 'foo' + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/staticmethods_test.py new/mockito-python-1.4.0/tests/staticmethods_test.py --- old/mockito-python-1.2.2/tests/staticmethods_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/staticmethods_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -18,10 +18,12 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -from .test_base import TestBase -from mockito import when, verify, unstub, any +from mockito import any, unstub, verify, when from mockito.verification import VerificationError +from .test_base import TestBase + + class Dog: @staticmethod def bark(): @@ -76,6 +78,14 @@ self.assertEqual("miau", Dog.barkHardly(1, 2)) + def testStubsWithArgsOnInstance(self): + dog = Dog() + self.assertEqual("woof woof", dog.barkHardly(1, 2)) + + when(Dog).barkHardly(1, 2).thenReturn("miau") + + self.assertEqual("miau", dog.barkHardly(1, 2)) + def testStubsButDoesNotMachArguments(self): self.assertEqual("woof woof", Dog.barkHardly(1, "anything")) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/stubbing_test.py new/mockito-python-1.4.0/tests/stubbing_test.py --- old/mockito-python-1.2.2/tests/stubbing_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/stubbing_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -19,9 +19,9 @@ # THE SOFTWARE. import pytest +from mockito import any, mock, times, verify, when from .test_base import TestBase -from mockito import mock, when, verify, times, any class TestEmptyMocks: @@ -375,7 +375,7 @@ self.assertEqual(m.with_key_words(testing="Very Funky"), "Very Funky Stuff") - def testSubsWithThenAnswerAndMixedArgs(self): + def testStubsWithThenAnswerAndMixedArgs(self): repo = mock() def method_one(value, active_only=False): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/unstub_test.py new/mockito-python-1.4.0/tests/unstub_test.py --- old/mockito-python-1.2.2/tests/unstub_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/unstub_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -1,6 +1,6 @@ import pytest -from mockito import when, unstub, verify, ArgumentError +from mockito import mock, when, unstub, verify, ArgumentError class Dog(object): @@ -31,6 +31,13 @@ assert mox.waggle() == 'Unsure' + def testUnconfigureMock(self): + m = mock() + when(m).foo().thenReturn(42) + assert m.foo() == 42 + unstub(m) + assert m.foo() is None + class TestAutomaticUnstubbing: def testWith1(self): @@ -128,3 +135,4 @@ assert rex.waggle() == 'Sure' verify(Dog).waggle() + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/mockito-python-1.2.2/tests/when_interface_test.py new/mockito-python-1.4.0/tests/when_interface_test.py --- old/mockito-python-1.2.2/tests/when_interface_test.py 2020-09-09 08:58:01.000000000 +0200 +++ new/mockito-python-1.4.0/tests/when_interface_test.py 2022-08-25 22:48:31.000000000 +0200 @@ -59,7 +59,7 @@ assert rex.waggle() == 'Sure' assert rex.weggle() == 'Sure' - # For documentation; the inital strict value of the mock will be used + # For documentation; the initial strict value of the mock will be used # here. So the above when(..., strict=False) just assures we can # actually *add* an attribute to the mocked object with pytest.raises(InvocationError):
