How do I mock a function with another function in python, that will also provide a mock object?
I have code that does something like:
def foo(arg1, arg2):
    r = bar(arg1)
    # does interesting things
I would like to substitute an implementation of the bar function, have it return sane values, and make sure it's called with the right arguments.
I've tried this, where fake_bar is my simple replacement for bar:
from unittest.mock import patch
def test_foo():
   with patch("x.bar", fake_bar) as mock_bar:
      actual = foo(arg1, arg2)
      assert actual == expected
      mock_bar.assert_called_once_with(arg1)
However, I get this error:
AttributeError: 'function' object has no attribute 'assert_called_once'
I found this question which suggests using create_autospec. However, mock.create_autospec does not preserve return values.
The python documentation suggests doing something like:
mock_function = create_autospec(function, return_value='fishy')
However, my faked version of bar has computed return values that are not static and not so simple to put into an inline lambda.
I feel like I'm missing something obvious. Is there a way to easily both mock a function and replace its implementation with something more complex than a static return value?
Use the wraps keyword argument:
def test_foo():
   with patch("x.bar", wraps=fake_bar) as mock_bar:
      actual = foo(arg1, arg2)
      assert actual == expected
      mock_bar.assert_called_once_with(arg1)
Here, x.bar is the fully qualified name of the function you are replacing, for example
'bigbusiness.account.AccountRepository.insert'.
mock_bar will still be a Mock (as is the default), but that Mock will wrap the function fake_bar, so the return value of mock_bar is the return value of fake_bar, rather than another Mock instance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With