2013-01-17 7 views
7

मैं के लिए एक इकाई परीक्षण लिखने के लिए प्रयास कर रहा हूँ एक वर्ग के __init__:मैं एक सुपरक्लास के __init__ को कैसे एक यूनिट परीक्षण के लिए एक मॉक ऑब्जेक्ट युक्त विशेषता बना सकता हूं?

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

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

config विशेषता सुपर के __init__ द्वारा निर्धारित है। मैं mock का उपयोग कर रहा हूं, और मैं कॉन्फ़िगरेशन विशेषता को नकली ऑब्जेक्ट बनाना चाहता हूं। हालांकि, मैं यह समझने में सक्षम नहीं हूं कि वास्तव में ऐसा कैसे किया जाए।

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' 

जाहिर है मैं 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() 

बहरहाल, यह काम नहीं करता है: यहाँ सबसे अच्छा मैं परीक्षा के लिए साथ आने सकता है , लेकिन मुझे कोई विचार नहीं है जहां बिल्कुल मुझे इसे स्थापित करना चाहिए। या उस मामले के लिए, यदि मैं जो करना चाहता हूं वह भी संभव है। क्या कोई मुझे बता सकता है कि मुझे यह काम करने के लिए क्या करना है?

+0

एक अवलोकन: 'सुपर' का वापसी मूल्य एक ऑब्जेक्ट नहीं है जिसमें' 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