How to check for mock calls with wildcards?

Question:

I am writing unit tests, and want to check for a call which has a function object, like so:

call(u'mock', u'foobar', <function <lambda> at 0x1ea99b0>, 10)

How do I check that the call() has all the parameters I want, without reproducing the lambda?

Edit: I wanted to clarify that I am using the mock library from here: http://mock.readthedocs.org/en/latest/. The call I showed above is a call on a MagicMock object, which I want to check using assert_has_calls.

Asked By: Rohan Dhruva

||

Answers:

not sure how you’re building the call, but if it’s some sort of args:

# IN THE CASE WE'RE DOING call(*args)

if all([len(args) == 4,isinstance(args[0],str),
       isinstance(args[1],str), hasattr(args[2],'__call__'),
       isinstance(args[3],int)]):
    # PASS
else:
    # FAIL

If you’re overly concerned about getting input that is a callable that ISN’T a function, and feel it will fail the unit test silently:

from types import FunctionType

isinstance(lambda x: x,FunctionType) # True
Answered By: Adam Smith

I finally found out how to do what I want. Basically, when using assert_has_calls, I wanted one parameter to match regardless of what it was (because I can’t recreate the lambda every time during test).

The way to do it is to use mock.ANY.

So, in my example, this could match the call:

mocked_object.assert_has_calls([
   call('mock', 'foobar', mock.ANY, 10)
])
Answered By: Rohan Dhruva

If you want more granularity than mock.ANY, you can make your own validator class for use in call comparisons like assert_has_calls, assert_called_once_with, etc.

class MockValidator(object):

    def __init__(self, validator):
        # validator is a function that takes a single argument and returns a bool.
        self.validator = validator

    def __eq__(self, other):
        return bool(self.validator(other))

Which can be used like:

import mock
my_mock = mock.Mock()
my_mock('foo', 8)

# Raises AssertionError.
my_mock.assert_called_with('foo', MockValidator(lambda x: isinstance(x, str)))

# Does not raise AssertionError.
my_mock.assert_called_with('foo', MockValidator(lambda x: isinstance(x, int)))
Answered By: Michael Tom
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.