# Path: mockito/mockito.py
# def when(obj, strict=True):
#     """Central interface to stub functions on a given `obj`
# 
#     `obj` should be a module, a class or an instance of a class; it can be
#     a Dummy you created with :func:`mock`. ``when`` exposes a fluent interface
#     where you configure a stub in three steps::
# 
#         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>`.
#     All invocations that do not match this specific call signature will be
#     rejected. They usually throw at call time.
# 
#     Stubbing in mockito's sense thus means not only to get rid of unwanted
#     side effects, but effectively to turn function calls into constants.
# 
#     E.g.::
# 
#         # Given ``dog`` is an instance of a ``Dog``
#         when(dog).bark('Grrr').thenReturn('Wuff')
#         when(dog).bark('Miau').thenRaise(TypeError())
# 
#         # With this configuration set up:
#         assert dog.bark('Grrr') == 'Wuff'
#         dog.bark('Miau')  # will throw TypeError
#         dog.bark('Wuff')  # will throw unwanted interaction
# 
#     Stubbing can effectively be used as monkeypatching; usage shown with
#     the `with` context managing::
# 
#         with when(os.path).exists('/foo').thenReturn(True):
#             ...
# 
#     Most of the time verifying your interactions is not necessary, because
#     your code under tests implicitly verifies the return value by evaluating
#     it. See :func:`verify` if you need to, see also :func:`expect` to setup
#     expected call counts up front.
# 
#     If your function is pure side effect and does not return something, you
#     can omit the specific answer. The default then is `None`::
# 
#         when(manager).do_work()
# 
#     `when` verifies the method name, the expected argument signature, and the
#     actual, factual arguments your code under test uses against the original
#     object and its function so its easier to spot changing interfaces.
# 
#     Sometimes it's tedious to spell out all arguments::
# 
#         from mockito import ANY, ARGS, KWARGS
#         when(requests).get('http://example.com/', **KWARGS).thenReturn(...)
#         when(os.path).exists(ANY)
#         when(os.path).exists(ANY(str))
# 
#     .. note:: You must :func:`unstub` after stubbing, or use `with`
#         statement.
# 
#     Set ``strict=False`` to bypass the function signature checks.
# 
#     See related :func:`when2` which has a more pythonic interface.
# 
#     """
# 
#     if isinstance(obj, str):
#         obj = get_obj(obj)
# 
#     theMock = _get_mock(obj, strict=strict)
# 
#     class When(object):
#         def __getattr__(self, method_name):
#             return invocation.StubbedInvocation(
#                 theMock, method_name, strict=strict)
# 
#     return When()
# 
# def patch(fn, attr_or_replacement, replacement=None):
#     """Patch/Replace a function.
# 
#     This is really like monkeypatching, but *note* that all interactions
#     will be recorded and can be verified. That is, using `patch` you stay in
#     the domain of mockito.
# 
#     Two ways to call this. Either::
# 
#         patch(os.path.exists, lambda str: True)  # two arguments
#         # OR
#         patch(os.path, 'exists', lambda str: True)  # three arguments
# 
#     If called with three arguments, the mode is *not* strict to allow *adding*
#     methods. If called with two arguments, mode is always `strict`.
# 
#     .. note:: You must :func:`unstub` after stubbing, or use `with`
#         statement.
# 
#     """
#     if replacement is None:
#         replacement = attr_or_replacement
#         return when2(fn, Ellipsis).thenAnswer(replacement)
#     else:
#         obj, name = fn, attr_or_replacement
#         theMock = _get_mock(obj, strict=True)
#         return invocation.StubbedInvocation(
#             theMock, name, strict=False)(Ellipsis).thenAnswer(replacement)


import mockito
import pytest
import numpy as np
from mockito import when, patch
from . import module



pytestmark = pytest.mark.usefixtures("unstub")


def xcompare(a, b):
    if isinstance(a, mockito.matchers.Matcher):
        return a.matches(b)

    return np.array_equal(a, b)


class TestEnsureNumpyWorks:
    def testEnsureNumpyArrayAllowedWhenStubbing(self):
        array = np.array([1, 2, 3])
        when(module).one_arg(array).thenReturn('yep')

        with patch(mockito.invocation.MatchingInvocation.compare, xcompare):
            assert module.one_arg(array) == 'yep'

    def testEnsureNumpyArrayAllowedWhenCalling(self):
        array = np.array([1, 2, 3])

# Path: mockito/mockito.py
# def when(obj, strict=True):
#     """Central interface to stub functions on a given `obj`
# 
#     `obj` should be a module, a class or an instance of a class; it can be
#     a Dummy you created with :func:`mock`. ``when`` exposes a fluent interface
#     where you configure a stub in three steps::
# 
#         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>`.
#     All invocations that do not match this specific call signature will be
#     rejected. They usually throw at call time.
# 
#     Stubbing in mockito's sense thus means not only to get rid of unwanted
#     side effects, but effectively to turn function calls into constants.
# 
#     E.g.::
# 
#         # Given ``dog`` is an instance of a ``Dog``
#         when(dog).bark('Grrr').thenReturn('Wuff')
#         when(dog).bark('Miau').thenRaise(TypeError())
# 
#         # With this configuration set up:
#         assert dog.bark('Grrr') == 'Wuff'
#         dog.bark('Miau')  # will throw TypeError
#         dog.bark('Wuff')  # will throw unwanted interaction
# 
#     Stubbing can effectively be used as monkeypatching; usage shown with
#     the `with` context managing::
# 
#         with when(os.path).exists('/foo').thenReturn(True):
#             ...
# 
#     Most of the time verifying your interactions is not necessary, because
#     your code under tests implicitly verifies the return value by evaluating
#     it. See :func:`verify` if you need to, see also :func:`expect` to setup
#     expected call counts up front.
# 
#     If your function is pure side effect and does not return something, you
#     can omit the specific answer. The default then is `None`::
# 
#         when(manager).do_work()
# 
#     `when` verifies the method name, the expected argument signature, and the
#     actual, factual arguments your code under test uses against the original
#     object and its function so its easier to spot changing interfaces.
# 
#     Sometimes it's tedious to spell out all arguments::
# 
#         from mockito import ANY, ARGS, KWARGS
#         when(requests).get('http://example.com/', **KWARGS).thenReturn(...)
#         when(os.path).exists(ANY)
#         when(os.path).exists(ANY(str))
# 
#     .. note:: You must :func:`unstub` after stubbing, or use `with`
#         statement.
# 
#     Set ``strict=False`` to bypass the function signature checks.
# 
#     See related :func:`when2` which has a more pythonic interface.
# 
#     """
# 
#     if isinstance(obj, str):
#         obj = get_obj(obj)
# 
#     theMock = _get_mock(obj, strict=strict)
# 
#     class When(object):
#         def __getattr__(self, method_name):
#             return invocation.StubbedInvocation(
#                 theMock, method_name, strict=strict)
# 
#     return When()
# 
# def patch(fn, attr_or_replacement, replacement=None):
#     """Patch/Replace a function.
# 
#     This is really like monkeypatching, but *note* that all interactions
#     will be recorded and can be verified. That is, using `patch` you stay in
#     the domain of mockito.
# 
#     Two ways to call this. Either::
# 
#         patch(os.path.exists, lambda str: True)  # two arguments
#         # OR
#         patch(os.path, 'exists', lambda str: True)  # three arguments
# 
#     If called with three arguments, the mode is *not* strict to allow *adding*
#     methods. If called with two arguments, mode is always `strict`.
# 
#     .. note:: You must :func:`unstub` after stubbing, or use `with`
#         statement.
# 
#     """
#     if replacement is None:
#         replacement = attr_or_replacement
#         return when2(fn, Ellipsis).thenAnswer(replacement)
#     else:
#         obj, name = fn, attr_or_replacement
#         theMock = _get_mock(obj, strict=True)
#         return invocation.StubbedInvocation(
#             theMock, name, strict=False)(Ellipsis).thenAnswer(replacement)


# Path: tests/numpy_test.py
import mockito
import pytest
import numpy as np
from mockito import when, patch
from . import module




pytestmark = pytest.mark.usefixtures("unstub")


def xcompare(a, b):
    if isinstance(a, mockito.matchers.Matcher):
        return a.matches(b)

    return np.array_equal(a, b)


class TestEnsureNumpyWorks:
    def testEnsureNumpyArrayAllowedWhenStubbing(self):
        array = np.array([1, 2, 3])
        when(module).one_arg(array).thenReturn('yep')

        with patch(mockito.invocation.MatchingInvocation.compare, xcompare):
            assert module.one_arg(array) == 'yep'

    def testEnsureNumpyArrayAllowedWhenCalling(self):
        array = np.array([1, 2, 3])

        when(module).one_arg(Ellipsis).thenReturn('yep')