Author breilly_box
Recipients breilly_box
Date 2019-11-06.22:59:47
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <>
mock.create_autospec is meant to create a mock that will ensure, among other things, that method calls on the mock correspond to real methods on the original object and that the arguments match the signature of the original method. However, if the original method is decorated with a method that returns a callable object, the signature check may fail.

Attached is a script that demonstrates the error.

The essential part of the script looks like this:
def decorator(m):
    return Wrapper(m)

class Wrapper(object):
    def __init__(self, method):
        self.method = method
        update_wrapper(self, method)

    def __call__(self, instance, *args, **kwargs):
        return self.__get__(instance, type(instance))(*args, **kwargs)

    def __get__(self, instance, owner):
        ... # do the wrapping

The `decorator` method returns an instance of the `Wrapper` class, which is callable. Mock will calculate the signature of a method wrapped with `decorator` to be equal to that of `Wrapper.__call__`, namely `(instance, *args, **kwargs)`. Consequently, calls to the mocked method...

1. will incorrectly fail if the method usually takes no arguments, and
2. will incorrectly pass if the method takes at least one argument but too many arguments are provided.

This list of incorrect behaviour is not exhaustive, but hopefully you get the point.

If anyone's concerned about real-life examples, this kind of wrapper is used, for example, in the public Box SDK, as shown here:
Date User Action Args
2019-11-06 22:59:48breilly_boxsetrecipients: + breilly_box
2019-11-06 22:59:48breilly_boxsetmessageid: <>
2019-11-06 22:59:48breilly_boxlinkissue38729 messages
2019-11-06 22:59:48breilly_boxcreate