Verification

Verify that the mock was called the way you intended
from pymoq.mocking.functions import FunctionMock, remove_self_parameter

from fastcore.basics import patch_to
from fastcore.test import test_fail

Proof of concept

from pymoq.mocking import objects
from typing import Protocol
Mock = objects.Mock
class IWeb(Protocol):
    def get(self, a: int, b:str, c:float|None=None):
        ...

Calls to the mock are recorded with the full argument list.

m = Mock(IWeb)

m.get(1,"2")

m.get._calls
[((None, 1, '2'), {'c': None})]

These can then be matched against any signature:

Constructin signature validator
from pymoq.argument_validators import AnyArg
from pymoq.signature_validators import signature_validator_from_arguments
from pymoq.mocking.functions import add_self_parameter
sign_val = signature_validator_from_arguments(['self', 'a', 'b', 'c'], AnyArg(), 1, "2", c=AnyArg())
Matching against recorded call
args, kwargs = m.get._calls[0]
kwargs = m.get.fill_up_arg_list(args, kwargs)

print(sign_val.is_valid(*args, **kwargs))
True

Implementation


source

VerifiedCalls

 VerifiedCalls
                (verified_calls:list[tuple[list[typing.Any],dict[str,typin
                g.Any]]], all_calls:list[tuple[list[typing.Any],dict[str,t
                yping.Any]]])

source

FunctionMock.verify

 FunctionMock.verify (*args, **kwargs)
m = Mock(IWeb)


m.get(1,"2")
m.get(2,"2")
m.get(2.3,"2")

calls = m.get.verify(int, "2")
assert calls.verified == 2
assert calls.verified_calls == [((None, 1, '2'), {'c': None}), ((None, 2, '2'), {'c': None})]

calls
VerifiedCalls(verified_calls=[((None, 1, '2'), {'c': None}), ((None, 2, '2'), {'c': None})], all_calls=[((None, 1, '2'), {'c': None}), ((None, 2, '2'), {'c': None}), ((None, 2.3, '2'), {'c': None})])
m.get.verify(int, "2").times(2)
m.get.verify(int, "2").more_than(1)
m.get.verify(int, "2").more_than_or_equal_to(2)
m.get.verify(int, "2").less_than(3)
m.get.verify(int, "2").less_than_or_equal_to(2)
m.get.verify(str, int).never()

A failing assertion gives the following error message:

try:
    m.get.verify(int, "2").times(1)
except Exception as e:
    print(e)
Expected 1 calls, got 2.
Matched Calls:
    ((None, 1, '2'), {'c': None})
    ((None, 2, '2'), {'c': None})
All Calls:
    ((None, 1, '2'), {'c': None})
    ((None, 2, '2'), {'c': None})
    ((None, 2.3, '2'), {'c': None})
test_fail(lambda: m.get.verify(int, "2").times(1))
test_fail(lambda: m.get.verify(int, "2").never())
test_fail(lambda: m.get.verify(int, "2").more_than(3))
test_fail(lambda: m.get.verify(int, "2").more_than_or_equal_to(3))
test_fail(lambda: m.get.verify(int, "2").less_than(1))
test_fail(lambda: m.get.verify(int, "2").less_than_or_equal_to(1))

Build library