class A():
def tmp(self):
print("hi")
def b(a):
a.tmp()
To check if tmp method is called in b, the recommended way is
a = A()
a.tmp = MagicMock()
b(a)
a.tmp.assert_called()
But tmp here is being mocked away and is not resulting in a "hi"
getting printed.
I would want my unit test to check if method tmp is called without mocking it away.
Is this possible?
I know this is not a standard thing to expect when writing unitests. But my use case (which is bit tricky) requires this.
You can set the Mock.side_effect
to be the original method.
from unittest.mock import MagicMock
class A():
def tmp(self):
print("hi")
def b(a):
a.tmp()
a = A()
a.tmp = MagicMock(side_effect=a.tmp)
b(a)
a.tmp.assert_called()
When side_effect
is a function (or a bound method in this case, which is a kind of function), calling the Mock
will also call the side_effect
with the same arguments.
The Mock()
call will return whatever the side_effect
returns, unless it returns the unnittest.mock.DEFAULT
singleton. Then it will return Mock.return_value
instead.
Or you can decorate the method to test:
def check_called(fun):
def wrapper(self, *args, **kw):
attrname = "_{}_called".format(fun.__name__)
setattr(self, attrname, True)
return fun(self, *args, **kw)
return wrapper
a = A()
a.tmp = check_called(a.tmp)
b(a)
assert(getattr(a, "_tmp_called", False))
but MagicMock's side_effect
is definitly a better solution if you're already using Mock ;)
In addition to @Patrick Haugh's answer , you can also pass the function to the wraps
argument (and it seems more semantically correct to me).
wraps: Item for the mock object to wrap. If wraps is not None then calling the Mock will pass the call through to the wrapped object (returning the real result). Attribute access on the mock will return a Mock object that wraps the corresponding attribute of the wrapped object (so attempting to access an attribute that doesn't exist will raise an AttributeError).
a = A()
a.tmp = MagicMock(wraps=a.tmp)
b(a)
a.tmp.assert_called()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.