diff --git a/.bumpversion.cfg b/.bumpversion.cfg
index 284e57e6efd3082cff63f9ae13b653d5b2b18d2a..33016387b6177c6402b6e2c2c233a8295908b5a6 100644
--- a/.bumpversion.cfg
+++ b/.bumpversion.cfg
@@ -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 @@ optional_value = release
 values = 
 	dev
 	release
-
diff --git a/.codespellrc b/.codespellrc
new file mode 100644
index 0000000000000000000000000000000000000000..4ca59efe4fc02992fff3dbd24aff7f0ead21d93f
--- /dev/null
+++ b/.codespellrc
@@ -0,0 +1,3 @@
+[codespell]
+skip=./docs/_build,./.mypy_cache,*.sublime-workspace,.git
+ignore-words-list=atleast
diff --git a/.github/workflows/test-lint-go.yml b/.github/workflows/test-lint-go.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1751a6ddad9cec572c09966193e3e892a7182ae2
--- /dev/null
+++ b/.github/workflows/test-lint-go.yml
@@ -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 --git a/.gitignore b/.gitignore
index 3f5268d8bf591abb66ff29aa5e1c232acac368ea..99a6b81057ee64a4b2fbe2749ac9f5574779e872 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 *.pyc
-build
+build/
+dist/
 docs/_build
 .eggs/
 .pytest_cache
-__pycache__
\ No newline at end of file
+__pycache__
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 75ae86ddaf020f74786c2da1730ffc43a5bb0899..0000000000000000000000000000000000000000
--- a/.travis.yml
+++ /dev/null
@@ -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 --git a/CHANGES.txt b/CHANGES.txt
index b563f914c600a62c77dc8454c31a69c51f7f8267..c2304777711d5c6d5bb37e26da1063d7af486650 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -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 @@ Release 1.2.0 (November 25, 2019)
 - @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 --git a/docs/nutshell.rst b/docs/nutshell.rst
index 2da28e415bdb58461832bc1bd430a3ce1267853a..0d1051d56f9f1dd876f4a829fe323f5f366d4a40 100644
--- a/docs/nutshell.rst
+++ b/docs/nutshell.rst
@@ -41,15 +41,14 @@ No difference whatsoever when you mock modules
     >>> 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 --git a/docs/walk-through.rst b/docs/walk-through.rst
index e1bbc7bbaa1f20e8c304979b46bf1fd25146a0ea..c8e7c101c92ceb47ae0a4435013fca01c9e603d0 100644
--- a/docs/walk-through.rst
+++ b/docs/walk-through.rst
@@ -19,6 +19,7 @@ There are of course reasons when you don't want to overspecify specific tests. Y
 
     # 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 @@ And because it's a similar pattern, we can introduce :func:`spy2` here. Spies ca
     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 @@ When patching, you **MUST** **not** forget to :func:`unstub` of course! You can
 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 @@ To start with an empty stub use :func:`mock`::
     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 --git a/mockito/__init__.py b/mockito/__init__.py
index 8de2c1c4e738a2950fc2337cbf37536dcaa6bb64..53bd3799d5332be0ec4e3f1b300788703b731fdc 100644
--- a/mockito/__init__.py
+++ b/mockito/__init__.py
@@ -44,7 +44,7 @@ from .matchers import *  # noqa: F401 F403
 from .matchers import any, contains, times
 from .verification import never
 
-__version__ = '1.2.2'
+__version__ = '1.4.0'
 
 __all__ = [
     'mock',
diff --git a/mockito/invocation.py b/mockito/invocation.py
index 10954c5c45dea4be1104f34d057ab1060031c127..6266b20ee43253c5a9285c521053577fc9c4c789 100644
--- a/mockito/invocation.py
+++ b/mockito/invocation.py
@@ -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 @@ class Invocation(object):
         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 @@ class RememberedInvocation(Invocation):
         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 @@ class MatchingInvocation(Invocation):
             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 @@ class VerifiableInvocation(MatchingInvocation):
         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 @@ def raise_(exception, *a, **kw):
     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 AnswerSelector(object):
 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 --git a/mockito/matchers.py b/mockito/matchers.py
index 9a445841f24b4d8d33791e91a71884799054e245..fb7c599816562de4303a5252035c36dd22ed2e0a 100644
--- a/mockito/matchers.py
+++ b/mockito/matchers.py
@@ -60,7 +60,7 @@ The one usage you should not care about is a loose signature when using
 """
 
 import re
-
+builtin_any = any
 
 __all__ = [
     'and_', 'or_', 'not_',
@@ -77,6 +77,7 @@ __all__ = [
     'kwargs', 'KWARGS'
 ]
 
+
 class _ArgsSentinel(object):
     def __repr__(self):
         return '*args'
@@ -106,10 +107,21 @@ KWARGS = kwargs = {KWARGS_SENTINEL: '_'}
 
 # """
 
+
+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 @@ class Or(Matcher):
             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 @@ class Matches(Matcher):
             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 matches(regex, flags=0):
 
 
 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 --git a/mockito/mocking.py b/mockito/mocking.py
index 0955e1979bf1c9e47024b7a73fc3fe2abcb574c1..fed48464a203106a7751439661662eb47c496ec1 100644
--- a/mockito/mocking.py
+++ b/mockito/mocking.py
@@ -33,6 +33,13 @@ __tracebackhide__ = operator.methodcaller(
     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 @@ class _Dummy(object):
     # 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 @@ class Mock(object):
         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 @@ class Mock(object):
     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 @@ class Mock(object):
             )
 
         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 @@ class Mock(object):
             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 @@ class Mock(object):
             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 @@ def mock(config_or_spec=None, spec=None, strict=OMITTED):
     """
 
     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 --git a/mockito/mockito.py b/mockito/mockito.py
index 53854febaad69c4dd9dfa01ee2d13822665cb76a..72b30a7165295a8fedab7e7ff610067101318e9c 100644
--- a/mockito/mockito.py
+++ b/mockito/mockito.py
@@ -164,7 +164,7 @@ def when(obj, strict=True):
         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 @@ def when2(fn, *args, **kwargs):
     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 --git a/mockito/signature.py b/mockito/signature.py
index fabef5f14e3c0aadbba44c1f297aafc58566f56a..aaa76deb9a739b10aad8848c936d3c93fe52755a 100644
--- a/mockito/signature.py
+++ b/mockito/signature.py
@@ -10,7 +10,7 @@ import types
 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 --git a/mockito/spying.py b/mockito/spying.py
index 2fa5b444a4cbf39af53d3c17d30e468585f5c593..fec365b360c4f5786de856f479afc239a39faeac 100644
--- a/mockito/spying.py
+++ b/mockito/spying.py
@@ -25,7 +25,6 @@ import inspect
 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 @@ def spy2(fn):  # type: (...) -> None
 
 
     """
-    if isinstance(fn, str):
-        answer = get_obj(fn)
-    else:
-        answer = fn
-
-    when2(fn, Ellipsis).thenAnswer(answer)
-
+    when2(fn, Ellipsis).thenCallOriginalImplementation()
diff --git a/mockito/utils.py b/mockito/utils.py
index 52e8be4e5019339d3c46777982cf81bf7dbb361f..15d56cda0b4d90c6ddf62d95b5c77802b67b7190 100644
--- a/mockito/utils.py
+++ b/mockito/utils.py
@@ -77,7 +77,7 @@ def find_invoking_frame_and_try_parse():
         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 --git a/mockito/verification.py b/mockito/verification.py
index e7f766e572abc4832069f4cce596606cf817808e..0f1726494059339e42180435f7d5bef7b4e6071a 100644
--- a/mockito/verification.py
+++ b/mockito/verification.py
@@ -22,6 +22,7 @@ import operator
 
 __all__ = ['never', 'VerificationError']
 
+
 class VerificationError(AssertionError):
     '''Indicates error during verification of invocations.
 
@@ -104,7 +105,7 @@ Instead got:
                 % (
                     invocation,
                     "\n    ".join(
-                        str(invoc) for invoc in reversed(invocations)
+                        str(invoc) for invoc in invocations
                     )
                 )
             )
@@ -130,13 +131,13 @@ class InOrder(object):
     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 --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000000000000000000000000000000000000..c7e52221e9cbb632d8ae8a94b11f19b0f6ac8cfa
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+asyncio_mode=auto
+xfail_strict=true
diff --git a/setup.py b/setup.py
index db955cf5df129c56903a67c8cfebcbe443dd7264..f785bcec48fa16876e85d0ff1a95610fa257da57 100755
--- a/setup.py
+++ b/setup.py
@@ -24,6 +24,7 @@ setup(name='mockito',
       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 @@ setup(name='mockito',
           '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 --git a/tests/call_original_implem_test.py b/tests/call_original_implem_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..aca48f1eeb27d36b7f8307b7b993f79ba2a69c10
--- /dev/null
+++ b/tests/call_original_implem_test.py
@@ -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 --git a/tests/ellipsis_test.py b/tests/ellipsis_test.py
index e4e586020721304a85502e9a4f70a25669c876eb..c39cd95b55e53a546ea9eaa84515a231eadba0f5 100644
--- a/tests/ellipsis_test.py
+++ b/tests/ellipsis_test.py
@@ -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 --git a/tests/instancemethods_test.py b/tests/instancemethods_test.py
index 860d31d43e12746bc8bc3591ce4400bafb61de55..297ca46df29a907333349e895b92d539c0330305 100644
--- a/tests/instancemethods_test.py
+++ b/tests/instancemethods_test.py
@@ -73,6 +73,14 @@ class InstanceMethodsTest(TestBase):
         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 --git a/tests/matchers_test.py b/tests/matchers_test.py
index 0ffcbc3b520f00b7a4229cdffaff34e5b658db05..0b33e9e4b094d4618b2f35b7b0cc30342a5c934b 100644
--- a/tests/matchers_test.py
+++ b/tests/matchers_test.py
@@ -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 MatchesMatcherTest(TestBase):
 
 
 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):
+    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()
-        c.matches("foo")
-        c.matches(123)
-        self.assertEqual(123, c.value)
 
+        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 --git a/tests/modulefunctions_test.py b/tests/modulefunctions_test.py
index 6d8728f320cb18c64e2198129201706264c5ee11..da8379c4e1249766a864cd4adecea7e33145779c 100644
--- a/tests/modulefunctions_test.py
+++ b/tests/modulefunctions_test.py
@@ -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 @@ class ModuleFunctionsTest(TestBase):
         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 --git a/tests/signatures_test.py b/tests/signatures_test.py
index d7c93c656bbd9705449b3db9967e92647479bf69..9fe0cc25f006a4f8c8807a63e41208d2742cbab5 100644
--- a/tests/signatures_test.py
+++ b/tests/signatures_test.py
@@ -8,7 +8,7 @@ from collections import namedtuple
 
 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 @@ class TestSignatures:
             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 --git a/tests/speccing_test.py b/tests/speccing_test.py
index 0ef5e701e97e684a9a6f223f23bbf7e9356b8f68..a3c974c543e16a4fbe0d073c621ccc8f7e476ae2 100644
--- a/tests/speccing_test.py
+++ b/tests/speccing_test.py
@@ -102,6 +102,21 @@ class TestSpeccing:
 
         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 --git a/tests/spying_test.py b/tests/spying_test.py
index f2fa87dc447ae2cf4e53a18aa25841d5d1070383..e3254438d5bd8a7e560f67dd39088b52dcdc8c11 100644
--- a/tests/spying_test.py
+++ b/tests/spying_test.py
@@ -154,3 +154,7 @@ class TestSpy2:
         assert dummy.return_args('box') == 'foo'
         assert dummy.return_args('fox') == 'fix'
 
+    def testSpyOnClass(self):
+        spy2(Dummy.foo)
+        assert Dummy().foo() == 'foo'
+
diff --git a/tests/staticmethods_test.py b/tests/staticmethods_test.py
index ee9a0f55db5d98e2dbe77680dece76d2513610b2..64426de8d97784429ce50903c851917584a2d115 100644
--- a/tests/staticmethods_test.py
+++ b/tests/staticmethods_test.py
@@ -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 @@ class StaticMethodsTest(TestBase):
 
         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 --git a/tests/stubbing_test.py b/tests/stubbing_test.py
index 6c520d33e9693cbb2d149d0c0e71da3adec9c495..2d0e2ba4c3be88d12084025463f22d379e6d9efc 100644
--- a/tests/stubbing_test.py
+++ b/tests/stubbing_test.py
@@ -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 @@ class StubbingTest(TestBase):
         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 --git a/tests/unstub_test.py b/tests/unstub_test.py
index 5743424b702cac6abdd85a207f5b0681c4370b09..e9cccee1e0da266b73b5939634811acbb8d89e5e 100644
--- a/tests/unstub_test.py
+++ b/tests/unstub_test.py
@@ -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 @@ class TestUntub:
 
         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 @@ class TestAutomaticUnstubbing:
                 assert rex.waggle() == 'Sure'
 
                 verify(Dog).waggle()
+
diff --git a/tests/when_interface_test.py b/tests/when_interface_test.py
index e5cef5341317d7c166d23ea2b678e0eb325ea30d..cbaafc1294fe5ce86b4e9da5aeb36f2e322acc0c 100644
--- a/tests/when_interface_test.py
+++ b/tests/when_interface_test.py
@@ -59,7 +59,7 @@ class TestPassAroundStrictness:
         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):