2011-11-18 18 views
78

मैं पाइथन के साथ mock का उपयोग कर रहा हूं और सोच रहा था कि उन दो दृष्टिकोणों में से कौन सा बेहतर है (पढ़ें: अधिक पायथनिक)।कक्षा का मज़ाक उड़ाते हुए: मॉक() या पैच()?

विधि एक: बस एक नकली वस्तु बनाएं और इसका उपयोग करें। कोड लगता है:

def test_one (self): 
    mock = Mock() 
    mock.method.return_value = True 
    self.sut.something(mock) # This should called mock.method and checks the result. 
    self.assertTrue(mock.method.called) 

विधि दो: उपयोग पैच एक नकली बनाने के लिए। कोड इस तरह दिखता है:

@patch("MyClass") 
def test_two (self, mock): 
    instance = mock.return_value 
    instance.method.return_value = True 
    self.sut.something(instance) # This should called mock.method and checks the result. 
    self.assertTrue(instance.method.called) 

दोनों विधियां एक ही काम करती हैं। मैं मतभेदों से अनिश्चित हूं।

क्या कोई मुझे प्रबुद्ध कर सकता है?

+9

एक व्यक्ति जो करने की कोशिश की कभी नहीं किया है या तो नकली() या पैच के रूप में, मुझे लगता है कि पहले संस्करण स्पष्ट है कि और पता चलता है कि आप क्या करना चाहते हैं, भले ही मैं की कोई समझ नहीं है वास्तविक अंतर मुझे नहीं पता कि यह किसी भी मदद की है या नहीं, लेकिन मैंने सोचा कि यह समझने में उपयोगी हो सकता है कि एक अनियमित प्रोग्रामर क्या महसूस कर सकता है। –

+1

@ माइकलब्रेनन: आपकी टिप्पणी के लिए धन्यवाद। यह वास्तव में उपयोगी है। – Sardathrion

उत्तर

107

mock.patchmock.Mock से बहुत अलग क्रिटर है। patch क्लास को मॉक ऑब्जेक्ट के साथ बदलता है और आपको नकली उदाहरण के साथ काम करने देता है। इस स्निपेट पर एक नज़र डालें:

>>> class MyClass(object): 
... def __init__(self): 
...  print 'Created [email protected]{0}'.format(id(self)) 
... 
>>> def create_instance(): 
... return MyClass() 
... 
>>> x = create_instance() 
Created [email protected] 
>>> 
>>> @mock.patch('__main__.MyClass') 
... def create_instance2(MyClass): 
... MyClass.return_value = 'foo' 
... return create_instance() 
... 
>>> i = create_instance2() 
>>> i 
'foo' 
>>> def create_instance(): 
... print MyClass 
... return MyClass() 
... 
>>> create_instance2() 
<mock.Mock object at 0x100505d90> 
'foo' 
>>> create_instance() 
<class '__main__.MyClass'> 
Created [email protected] 
<__main__.MyClass object at 0x100505d90> 

patch एक तरीका है कि आप कार्यों, जिसे आप कॉल में वर्ग के उपयोग को नियंत्रित करने की अनुमति देता में MyClass बदल देता है। एक बार जब आप कक्षा को पकड़ लेते हैं, कक्षा के संदर्भों को पूरी तरह से नकली उदाहरण द्वारा प्रतिस्थापित किया जाता है।

mock.patch आमतौर पर तब प्रयोग किया जाता है जब आप किसी ऐसे परीक्षण का परीक्षण कर रहे हैं जो परीक्षण के अंदर कक्षा का एक नया उदाहरण बनाता है। mock.Mock उदाहरण स्पष्ट हैं और पसंदीदा हैं। यदि आपके self.sut.something विधि ने पैरामीटर के रूप में उदाहरण प्राप्त करने के बजाय MyClass का उदाहरण बनाया है, तो mock.patch यहां उचित होगा।

+2

@ डी। शॉली हम किसी अन्य वर्ग के अंदर तत्काल कक्षा में कैसे पैच करते हैं जिसे परीक्षण में होना आवश्यक है। – ravi404

+4

@ravz - ["कहाँ से पैच"] दें (https://mock.readthedocs.org/en/latest/patch.html#where-to-patch) एक पठन। यह ठीक से काम करने के लिए और अधिक कठिन चीजों में से एक है। –

+0

मेरा नकली परीक्षण ** विधि दो ** के समान है। मैं MyClass उदाहरण अपवाद बढ़ाने के लिए चाहता हूँ। मैंने mock.side_effect और mock.return_value.side_effect दोनों की कोशिश की है और वे काम नहीं करते हैं। मैं क्या करूं? – Hussain

4

मुझे इस पर YouTube video मिला है।

संक्षिप्त उत्तर: mock का उपयोग करें जब आप उस चीज़ में गुजर रहे हैं जिसे आप मॉक करना चाहते हैं, और patch यदि आप नहीं हैं। दोनों में से, नकली दृढ़ता से प्राथमिकता दी जाती है क्योंकि इसका मतलब है कि आप उचित निर्भरता इंजेक्शन के साथ कोड लिख रहे हैं।

बेवकूफ उदाहरण:

# Use a mock to test this. 
my_custom_tweeter(twitter_api, sentence): 
    sentence.replace('cks','x') # We're cool and hip. 
    twitter_api.send(sentence) 

# Use a patch to mock out twitter_api. You have to patch the Twitter() module/class 
# and have it return a mock. Much uglier, but sometimes necessary. 
my_badly_written_tweeter(sentence): 
    twitter_api = Twitter(user="XXX", password="YYY") 
    sentence.replace('cks','x') 
    twitter_api.send(sentence) 
संबंधित मुद्दे