Python Patch / Mock类方法,但仍调用原始方法

时间:2019-04-29 07:33:24

标签: python mocking

我想使用补丁来记录对类中某个函数的所有函数调用以进行单元测试,但需要原始函数仍按预期运行。我在下面创建了一个虚拟代码示例:

from mock import patch

class A(object):
    def __init__(self):
        self._a = 1

class B(A):
    def __init__(self):
        super(B, self).__init__() # TypeError: super() argument 1 must be type, not MagicMock
        self._b = 11

    def bar(self, b):
        self._b = self._b + 1 + b

    def foo(self, b):
        self.bar(b)

class MockB(B):
    def foo(self, b):
        super(MockB, self).foo(self, b)

@patch('main.B')
def main(b_class):
    b_class.side_effect = MockB

    b = B()

    print b._b # 11
    b.foo(0)
    print b._b # 12

main()

在我的情况下,类b = B()的实例实际上不在主函数中,而是在另一个模块中,因此我无法模拟该实例。我一般需要它作为B的所有实例的装饰器。

摘要:我不确定如何单独模拟类方法,但是仍然调用原始方法。之后,我想使用类似call_args_list的名称,在其中可以看到对foo()的所有呼叫。

3 个答案:

答案 0 :(得分:1)

我认为您正在寻找wraps Mock参数。在官方documentation中搜索wraps。访问属性返回一个模拟对象,但是如果未为该模拟配置返回值,则调用方法将提供真实的方法结果。

答案 1 :(得分:1)

更多详细信息请参见:https://stackoverflow.com/a/61963740/1731460

const isLongitude = num => isFinite(num) && Math.abs(num) <= 180;

答案 2 :(得分:0)

只需保留对原始、非模拟/修补的实例的引用即可。

我在修补 ctypes.windll.winmm.mciSendStringW 时遇到了问题,但我仍然希望能够访问该原始函数。最初,我曾尝试过:

from ctypes import windll
originalWindll = windll

# Later on trying to call the original mciSendStringW when it's patched...
originalWindll.winmm.mciSendStringW(...)  # Didn't work! Called the patched version of the function!

正确的做法实际上是这样...因为它是被模拟/修补的函数,所以我需要保留对它的引用。

from ctypes import windll
originalMCISendStringW = windll.winmm.mciSendStringW

# Later on trying to call the original mciSendStringW when it's patched...
originalMCISendStringW(...)  # Works! Calls the original, non-patched version of this function!