2013-01-17 50 views
7

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

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

     if configFile == "configfile.txt": 
      self.config.MakeDevBuild() 

的配置属性由超级的__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() 

但是,这并不工作 - 我得到一个错误:

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' 

显然我没有设置正确的配置属性,但我不知道其中正是我应该设置它。或者就此而言,如果我想要做什么甚至是可能的。任何人都可以告诉我我需要做些什么来完成这项工作?

+0

的观察: 'super'的返回值不是具有'config'属性的对象,而是具有'__init__'方法的对象,该方法将向其参数添加一个'config'属性。 – chepner

+0

是整个'__init__'吗?如果是,那么只有在你的测试中没有传递配置文件名时才会添加self.config.MakeDevBuild。 – jlujan

回答

16

你不能直接设置它嘲笑__init__ - 见_unsupported_magics in mock.py

至于你能做什么,你可以通过它来修补,像这样嘲笑__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() 

其中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() 

其作品,但也相当难看..

+1

谢谢,第一种方法做了我所需要的。 – khagler