【问题标题】:How to write a mock that works with decorators?如何编写与装饰器一起使用的模拟?
【发布时间】:2021-04-19 17:18:02
【问题描述】:

我有现有的单元测试来模拟 python 类的方法,并且它们已经成功运行了一段时间。现在,我将 AWS xray 装饰器添加到我的一个模拟方法中,并且对该模拟的调用失败并出现“缺少必需的参数”异常。

这是带有 myMethod() 函数的类的一部分,它接受 2 个参数。函数定义之前的 xray_recorder.capture 装饰器是新添加的:

@xray_recorder.capture()    
def myMethod(self, dbConn, userSession):
    ...
    

在我的单元测试中,我模拟了这个类和函数,如下所示:

mock_myClass = mock.create_autospec(myClass)
mock_myClass.myMethod.return_value = {
    'attr1': 'value1',
    ...
}

当调用者在常规使用中调用该方法时,它可以正常工作。但在我的单元测试中它失败了。这是对方法的调用:

            retVal = mock_myClass.myMethod(dbConn, userSession)

此调用现在引发异常:缺少必需的参数:'userSession'

我还尝试使用 args 和 kwargs 定义模拟 myMethod:

def mocked_myMethod(*args, **kwargs): 返回 { 'attr1': '值1', ... }

并使用:

mock_myClass.myMethod.side_effect = mocked_myMethod

但这以同样的方式失败。

我的理解是装饰器必须将参数列表传递给他们正在调用的函数。如果我从 aws_xray_sdk 查看 xray_recorder.capture() 的源代码,我会看到:

def capture(self, name=None):
    """
    A decorator that records enclosed function in a subsegment.
    It only works with synchronous functions.

    params str name: The name of the subsegment. If not specified
    the function name will be used.
    """
    return self.in_subsegment(name=name)

...

def in_subsegment(self, name=None, **subsegment_kwargs):
    """
    Return a subsegment context manger.

    :param str name: the name of the subsegment
    :param dict subsegment_kwargs: remaining arguments passed directly to `begin_subsegment`
    """
    return SubsegmentContextManager(self, name=name, **subsegment_kwargs)

我怎样才能让我的模拟工作与这个一起工作?

【问题讨论】:

    标签: python python-unittest


    【解决方案1】:

    您需要在模拟对象上调用myMethod,而不是类本身才能使其工作。

    mock_myClass = mock.create_autospec(myClass)
    ...
    retVal = mock_myClass.myMethod(dbConn, userSession) # Note use of mock_MyClass
    

    调用myClass.myMethod(...) 将直接调用类上的方法,绕过模拟。

    【讨论】:

    • 对不起,这是我在做的,我在原始问题报告中输入错误。我现在已经更正了。
    猜你喜欢
    • 2012-09-01
    • 2012-12-17
    • 2018-04-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-12
    • 2016-03-19
    • 2016-09-12
    • 2014-12-31
    相关资源
    最近更新 更多