Check unittest.mock invocation arguments agnostically wrt whether they were passed as positional arguments or keyword arguments

When the unittest.mock.Mock object was called, I can check the values โ€‹โ€‹of the arguments with the exact signature of the call:

 from unittest.mock import Mock m = Mock() # creation of mock m('foo', bar='baz') # call to the mock m.assert_called_once_with('foo', bar='baz') # check call arguments 

Verification of another signature with the same values โ€‹โ€‹will fail. For example, if we check with 'baz' as a positional argument instead of a named argument, the statement will fail:

 m.assert_called_once_with('foo', 'baz') # AssertionError: Expected call: mock('foo', 'baz') # Actual call: mock('foo', bar='baz') 

He must. If the function replaced by m was

 def actual_fu(foo, bar): # do something 

then the calls will be equivalent, but if it was

 def a_different_actual_fu(foo, *args, bar='some default'): # do something 

then the calls will not be equivalent. Mock does not know the actual signature of the function, so it cannot rely on the equivalence that we would have in the first case.

Is there a way to check the values โ€‹โ€‹of call arguments that are agnostic about whether they were passed positionally or as keyword arguments , letting Mock (or an auxiliary statement function or the like) know about the actual function is replaced by the layout?

A Mock object can be notified of an object that it replaces (which can be a function or method), with an optional spec argument or with autospeccing , but they serve a different purpose (limiting which calls to allow for the layout) and do not affect post-fact checking .

+6
source share
1 answer

A Mock object may be informed of an object that it replaces (which may be a function or method), with an optional spec argument or with autospeccing , but they serve a different purpose.

This is exactly what Problem 17015: The layout may be smarter and validate the signature specification . spec is actually very tightly coupled and now makes the layout a signature function.

See how the poppy fails when we claim that mock was called with the keyword argument - without telling it the actual function signature:

 >>> from unittest.mock import Mock >>> >>> def actual_fu(foo, bar): ... pass >>> >>> m = Mock() >>> m('foo', bar='baz') <Mock name='mock()' id='4356741496'> >>> >>> m.assert_called_once_with(foo='foo', bar='baz') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py", line 803, in assert_called_once_with return self.assert_called_with(*args, **kwargs) File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py", line 792, in assert_called_with raise AssertionError(_error_message()) from cause AssertionError: Expected call: mock(bar='baz', foo='foo') Actual call: mock('foo', bar='baz') 

And now, let's see how all this goes, if we provide a spec :

 >>> m = Mock(spec=actual_fu) >>> m('foo', bar='baz') <Mock name='mock()' id='4356249528'> >>> >>> m.assert_called_once_with(foo='foo', bar='baz') >>> m.assert_called_once_with('foo', bar='baz') >>> m.assert_called_once_with(bar='baz', foo='foo') >>> m.assert_called_once_with('foo', 'baz') >>> 

(Used by Python 3.5.1)

+3
source

All Articles