Python unittest mock:是不是可以在测试时模拟 __init__ 的默认参数的值?

Posted

技术标签:

【中文标题】Python unittest mock:是不是可以在测试时模拟 __init__ 的默认参数的值?【英文标题】:Python unittest mock: Is it possible to mock the value of the __init__'s default arguments at test time?Python unittest mock:是否可以在测试时模拟 __init__ 的默认参数的值? 【发布时间】:2018-11-08 09:58:43 【问题描述】:

我想通过在单元测试期间替换默认参数的值来测试使用默认参数创建的类。

例如,我想要以下行(整个代码) obj = SomeClass()

看起来像是用参数调用的

obj = SomeClass(overiden_parameter)

一种解决方案可能是创建简单的子类:

``` def OriginalClass(object):

def __init_(some_param="default_value"):
    ...

```

``` def MockedOriginalClass(OriginalClass):

def __init_():
    super(MockedOriginalClass, self).__init__("some_other_value)
    ...

```

如何通过代码模拟/修补OriginalClass 成为MockedOriginalClass?请记住,我确实想保留原始类的功能,我想要更改的唯一一件事是它的默认 __init__ 参数。

我觉得这对 Mocking 来说是一件非常简单的事情,我只是不知道该怎么做。

我发现了这个问题: Python unittest mock: Is it possible to mock the value of a method's default arguments at test time?

非常接近,但我认为不能将相同的技巧应用于__init__ 方法。

【问题讨论】:

你不能只模拟SomeClass,然后让模拟就像传入参数一样? 我认为您可能是对的,我正在研究如何模拟/修补现有的 SomeClass 用法,只需修补一个默认输入参数。 【参考方案1】:

做到这一点的一种方法是为您的特定测试模拟整个班级,如下所示:

示例: 我有一个类 SomeClass 我想模拟。我的模拟类名称是 MockSomeClass,它将模拟 SomeClass 类。

class MockSomeClass(SomeClass):
    '''
    Mock Class
    '''
    def __init__(overiden_parameter):
        self.overiden_parameter = overiden_parameter

因此,在测试期间,您将使用具有覆盖功能的模拟类,而其他功能的行为将保持不变(继承)。

打补丁

mock_some_class_obj = MockSomeClass()

@mock.patch('SomeClass', return_value=mock_some_class_obj)
def test1(self, mock_some_class_obj):
'''
Test 1
'''
    obj = SomeClass()

catch 所以在代码中,每当您创建 SomeClass 的对象时,都会返回模拟类的对象。在模拟类中,您可以添加自己的功能。

【讨论】:

这对现有库有何帮助?您是否期望我们会替换所有现有代码来使用这个新类?您可能有部分答案,缺少的是如何用这个新类“修补”现有类。 MockSomeClass 是原始类的子类还是 mock.Mock 它是原始类的子类 我上面描述的方法只会覆盖子类中 init 方法的功能,而其他方法/函数的行为将与 main/base 中的相同类。 这不好,我确实需要这个类,只需要通过更改 init 默认参数值来调整它的行为。【参考方案2】:

查看@Martinj Pieters 评论,但或者,您可以使用 pytest https://docs.pytest.org/en/documentation-restructure/how-to/monkeypatch.html 中支持的猴子补丁 https://en.wikipedia.org/wiki/Monkey_patch 来覆盖 __init__ 方法。

【讨论】:

以上是关于Python unittest mock:是不是可以在测试时模拟 __init__ 的默认参数的值?的主要内容,如果未能解决你的问题,请参考以下文章

[Python Modules] unittest.mock

Python 3 unittest不能在函数内部使用mock方法

python unittest

使用 unittest.mock 在 python 中修补 SMTP 客户端

使用unittest.mock在python中修补SMTP客户端

Python 3:unittest.mock如何为特定输入指定不同的返回值?