2013-01-17 39 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

相關問題