如何模拟超类的__init__为单元测试创​​建包含模拟对象的属性?

kha*_*ler 10 python mocking

我正在尝试为一个类写一个单元测试__init__:

def __init__(self, buildNum, configFile = "configfile.txt"):
        super(DevBuild, self).__init__(buildNum, configFile)

        if configFile == "configfile.txt":
            self.config.MakeDevBuild()
Run Code Online (Sandbox Code Playgroud)

config属性由super设置__init__.我正在使用mock,我希望config属性是一个模拟对象.但是,我还没弄清楚如何实现这一目标.这是我能为测试提出的最好的:

def test_init(self):
        with patch('DevBuild.super', create=True) as mock_super:
            mock_MakeDevBuild = MagicMock()
            mock_super.return_value.config.MakeDevBuild = mock_MakeDevBuild

            # Test with manual configuration
            self.testBuild = DevBuild("42", "devconfigfile.txt")
            self.assertFalse(mock_MakeDevBuild.called)

            # Test with automated configuration
            self.testBuild = DevBuild("42")
            mock_MakeDevBuild.assert_called_once_with()
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用 - 我收到一个错误:

Error
Traceback (most recent call last):
  File "/Users/khagler/Projects/BuildClass/BuildClass/test_devBuild.py", line 17, in test_init
    self.testBuild = DevBuild("42")
  File "/Users/khagler/Projects/BuildClass/BuildClass/DevBuild.py", line 39, in __init__
    self.config.MakeDevBuild()
AttributeError: 'DevBuild' object has no attribute 'config'
Run Code Online (Sandbox Code Playgroud)

显然我没有正确设置配置属性,但我不知道我应该在哪里设置它.或者就此而言,如果我想做的事情是可能的.任何人都可以告诉我我需要做些什么来使这项工作?

jko*_*era 20

您不能通过__init__直接设置来模拟- 请参阅mock.py中的_unsupported_magics.

至于你可以做什么,你可以__init__通过将其传递给补丁来进行模拟,如下所示:

mock_makeDevBuild = MagicMock()
def mock_init(self, buildNum, configFile):
    self.config = MagicMock()
    self.config.MakeDevBuild = mock_makeDevBuild

with patch('DevBuild.SuperDevBuild.__init__', new=mock_init):
    DevBuild("42")
    mock_makeDevBuild.assert_called_once_with()
Run Code Online (Sandbox Code Playgroud)

其中SuperDevBuild是DevBuild的基类.

如果你真的想要模拟super(),你可以创建一个类,然后__init__手动绑定到对象,就像

mock_makeDevBuild = MagicMock()
def get_mock_super(tp, obj):
    class mock_super(object):
        @staticmethod
        def __init__(buildNum, configFile):
            obj.config = MagicMock()
            obj.config.MakeDevBuild = mock_makeDevBuild
    return mock_super
with patch('DevBuild.super', create=True, new=get_mock_super):
    DevBuild("42")
    mock_makeDevBuild.assert_called_once_with()
Run Code Online (Sandbox Code Playgroud)

哪个有效,但很难看......