python check if a method is called without mocking it away

ぃ、小莉子 提交于 2019-12-22 04:56:11

问题


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.


回答1:


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.




回答2:


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 ;)



来源:https://stackoverflow.com/questions/50970170/python-check-if-a-method-is-called-without-mocking-it-away

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!