I'd like to capture the return value of an inner function without having to explicitly return that return value from the outer function.
So I'd like to do something like this:
# bar.py
import foo
def my_fn():
foo.fn()
# test.py
from mock import patch
import foo
import bar
@patch("foo.fn")
def test_bar(mock_foo_fn):
bar.my_fn()
# assert isinstance(mock_foo_fn.return_value, dict)
without having to do this:
# bar.py
import foo
def my_fn():
return foo.fn()
CodePudding user response:
I have a cleaner solution, using a spy
.
The
mocker.spy
object acts exactly like the original method in all cases, except the spy also tracks function/method calls, return values and exceptions raised.
The spy is provided from the mocker
fixture of the plugin pytest-mock
. Usage demo for your example:
# test.py
import pytest
import bar
def test_bar(mocker):
spy = mocker.spy(bar.foo, "fn")
bar.my_fn()
spy.assert_called_once_with()
assert spy.spy_return == {"k": "v"}
CodePudding user response:
This might be more complicated than necessary, but I think you need to patch foo.fn
with a callable object that capture the return value of the original function, and not just a Mock
. Something like
class Wrapper:
def __init__(self, f):
self.f = f
def __call__(self, *args, **kwargs):
self.rv = self.f(*args, **kwargs)
with patch('foo.fn', new=Wrapper(foo.fn)) as m:
my_fn()
assert isinstance(m.rv, dict)
(Using something like with patch('foo.fn', wraps=foo.fn)
is not sufficient, because while that ensures that foo.fn
itself is called when the mock is called, the mock itself doesn't not capture the resulting return value.)