मॉकिंग एक वर्ग: मॉक () या पैच ()?


116

मैं पायथन के साथ नकली का उपयोग कर रहा हूं और सोच रहा था कि उन दोनों दृष्टिकोणों में से कौन सा बेहतर है (पढ़ें: अधिक पायथोनिक)।

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

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)

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

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


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

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

जवाबों:


151

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

>>> class MyClass(object):
...   def __init__(self):
...     print 'Created MyClass@{0}'.format(id(self))
... 
>>> def create_instance():
...   return MyClass()
... 
>>> x = create_instance()
Created MyClass@4299548304
>>> 
>>> @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 MyClass@4300234128
<__main__.MyClass object at 0x100505d90>

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

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


2
@ D.Shawley कैसे हम एक वर्ग को दूसरी कक्षा के अंदर तात्कालिक रूप से पैच करते हैं जिसे परीक्षण करने की आवश्यकता होती है।
रविवि २०

4
@ravz - " व्हेक टू पैच" एक रीड दे। यह ठीक से काम करने के लिए अधिक कठिन चीजों में से एक है।
डी। शेले

मेरा मॉक टेस्ट मेथड दो के समान है । मैं एक अपवाद बढ़ाने के लिए MyClass का उदाहरण चाहता हूं। मैंने mock.side_effect और mock.return_value.side_effect दोनों की कोशिश की है और उन लोगों ने काम नहीं किया। मैं क्या करूं?
हुसैन

5
@ D.Shawley लिंक टूट गया है, यह अब यहाँ पाया जा सकता है: "कहाँ पैच करने के लिए"
RazerM

2
किसी क्लास ऑब्जेक्ट को पैच करने के लिए stackoverflow.com/questions/8469680/…
storm_m2138

27

मुझे इस पर एक YouTube वीडियो मिला है ।

संक्षिप्त उत्तर: 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)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.