pythonmockingpython-unittestundocumented-behavior

How does the (undocumented) return_value argument for unittest.mock.patch work?


I've seen examples of unittest.mock.patch() and unittest.mock.patch.object() directly using a return_value argument.

Example:

with patch.object(ProductionClass, 'method', return_value=None) as mock_method:
    thing = ProductionClass()
    thing.method(1, 2, 3)

However, this argument is not officially documented for unittest.mock.patch() nor unittest.mock.patch.object(). (It is however used in the examples of the official documentation).

Is this supported or is it undefined behavior? Is it supposed to be documented and isn't? Do these examples work by coincidence? What does this argument do; does it do something unintuitive, or is it self-explanatory?


Solution

  • From the documentation for mock.patch:

    patch() takes arbitrary keyword arguments. These will be passed to AsyncMock if the patched object is asynchronous, to MagicMock otherwise or to new_callable if specified.

    From the documentation of mock.patch.object:

    Like patch(), patch.object() takes arbitrary keyword arguments for configuring the mock object it creates.

    And from the documentation of mock.Mock, where it is actually used:

    return_value: The value returned when the mock is called. By default this is a new Mock (created on first access). See the return_value attribute.

    And for good measure, the documentation of the return_value attribute, which shows the usage with examples:

    Set this to configure the value returned by calling the mock:

    >>> mock = Mock()
    >>> mock.return_value = 'fish'
    >>> mock()
    'fish'
    

    The default return value is a mock object and you can configure it in the normal way:

    >>> mock = Mock()
    >>> mock.return_value.attribute = sentinel.Attribute
    >>> mock.return_value()
    <Mock name='mock()()' id='...'>
    >>> mock.return_value.assert_called_with()
    

    return_value can also be set in the constructor:

    >>> mock = Mock(return_value=3)
    >>> mock.return_value
    3
    >>> mock()
    3
    

    So, as you can see, this is all well documented, though admittedly it may be overlooked at a first glance due to the arguments not present in the signature.