2012-08-31 14 views
12

के साथ बेस क्लास का नकल कैसे करें I Python में कुछ यूनिट-टेस्ट लिखने के लिए mock का उपयोग करने का प्रयास करें।पाइथन मॉक लाइब्रेरी

उदाहरण के लिए मैं निम्नलिखित वर्ग है:

class TCPHandler(socketserver.BaseRequestHandler): 
    def handle(self): 
     self.data = self.request.recv(1024).strip() 

और मैं केवल handle विधि का परीक्षण करना चाहते। socketserver.BaseRequestHandler के बारे में कुछ भी मानने के बिना। उदाहरण के लिए मैं यह कहना चाहता हूं कि handlerecv पर 1024 तर्क के साथ कॉल करना चाहता है। क्या नकली के साथ ऐसी चीज करना संभव है? अर्थात। एक वर्ग के साथ बेस क्लास socketserver.BaseRequestHandler को बदल रहा है? या क्या मैं उस विचार से ट्रैक कर रहा हूं?


ecatmur के जवाब के साथ

(! धन्यवाद) मैं पहली बार करने की कोशिश की है:

patcher = patch.object(TCPHandler, '__bases__', (Mock,)) 
with patcher: 
    patcher.is_local = True 
    handler = TCPHandler() 
    handler.handle() 

लेकिन अब handle नहीं बुलाया जाता है anylonger और dir(handler) देता है:

['assert_any_call', 'assert_called_once_with', 'assert_called_with', 'assert_has_calls', 'attach_mock', 'call_args', 'call_args_list', 'call_count', 'called', 'configure_mock', 'method_calls', 'mock_add_spec', 'mock_calls', 'reset_mock', 'return_value', 'side_effect'] 

type(handler) देता है <class 'mock.TCPHandler'>

जो मैं समझता हूं कि बेस क्लास को पैच करने से मेरी व्युत्पन्न कक्षा भी नकली हो जाती है।

mock = MagicMock() 
TCPHandler.handle(mock) 
#assertions 

हालांकि नकली नहीं लगता है के नाम से जाना:


मैं अब एक और विचार एक कोशिश दे दी है।

def test_derived(): 
    patcher = mock.patch.object(Derived, '__bases__', (mock.Mock,)) 
    with patcher: 
     patcher.is_local = True 
     d = Derived() 
     print d.foo() 

is_local हैक आवश्यक है जब पैच पीछे delattr कॉल करने के लिए कोशिश कर रहा से mock.patch को रोकने के लिए:

उत्तर

17

आप व्युत्पन्न वर्ग के __bases__ पैचिंग कर ऐसा कर सकते हैं।

+0

मैंने आपके संकेत का पालन किया लेकिन परिणाम यह था कि व्युत्पन्न वर्ग की विधि को नकली द्वारा प्रतिस्थापित किया गया है। –

+0

यदि आपने कोई नज़र डाली है तो मैंने अपना वर्तमान टेस्ट कोड प्रश्न में रखा है? तुम्हारी सहायता सराहनीय है। –

+0

@FrederickRoth भी यकीन नहीं है; यह पाइथन 2 के साथ मेरे लिए ठीक काम करता है। शायद उस ऑब्जेक्ट के हिस्सों को मजाक करने का प्रयास करें जो विधि तक पहुंचता है? – ecatmur

4

मुझे लगता है कि समस्या वास्तव में है कि आप वास्तविक कोड आप परीक्षण करना चाहते उपहास करने के लिए कोशिश कर रहे हैं। बल्कि वस्तुओं है कि उस कोड से कहा जा रहा है की तुलना में। आप संभाल प्रणाली को बुलाती है self.request पर recv विधि तो recv विधि बाहर नकली है कि क्या देखने में रुचि रखते हैं।

def test_tcp_handler_method(self): 

    handler = TCPHandler() 
    handler.request = Mock() 

    handler.handle() 

    self.assertTrue(handler.request.recv.called) 
    self.assertEqual(handler.request.recv.call_args[0], 1024) 

आपको हैंडलर को तुरंत चालू करने के लिए कुछ अतिरिक्त सेटअप करना पड़ सकता है लेकिन बुनियादी विचार स्पष्ट होना चाहिए।

+0

आपके इनपुट के लिए धन्यवाद! टीसीपीहैंडलर को तत्काल करने के लिए एक tcprequest की आवश्यकता होती है और इसलिए मेरे कोड द्वारा सीधे नहीं किया जाता है, लेकिन टीसीपीएस सर्वर द्वारा। यही कारण है कि मैं इसे '__init__' नहीं कहूंगा। मैं बस पूरे टीसीपीएस सर्वर ढांचे का परीक्षण किए बिना अपनी छोटी सी विधि का परीक्षण करना चाहता हूं। –

4

अगर यह सबसे अच्छा समाधान है, लेकिन मैं type() का उपयोग कर एक अलग माता पिता के साथ पिछले वर्ग को पुनर्परिभाषित करने में कामयाब मैं नहीं जानता।

from contextlib import contextmanager 

@contextmanager 
def patch_parent(class_): 
    """ 
    Mock the bases 
    """ 
    yield type(class_.__name__, (Mock,), dict(class_.__dict__)) 

इस के बाद, आप उपयोग कर सकते हैं patch_parent इस तरह::

class Bar(): 
    def method(self, param1, param2...): 
     ... 

class Foo(Bar): 
    pass 


>>> with patch_parent(Foo) as MockFoo: 
...  f = MockFoo() 
...  print f 
...  print f.method() 
... 
<Foo id='15488016'> 
<Foo name='mock.method()' id='15541520'> 
>>> s = Foo() 
>>> s.method() 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: method() takes exactly 3 arguments (1 given) 

MockFoo वर्ग अभी भी करने के तरीकों है मैं एक समारोह patch_parent() कहा जाता है, कि एक माता पिता नकली के साथ वर्ग रिटर्न बनाया Foo कक्षा और इसमें माता-पिता में परिभाषित विधियां नहीं हैं क्योंकि माता-पिता अब Mock कक्षा है।

संबंधित मुद्दे