मॉक बनाम मैजिकमॉक


138

मेरी समझ यह है कि मैजिकमॉक मॉक का एक सुपरसेट है जो स्वचालित रूप से "मैजिक मेथड्स" करता है, इस प्रकार सूची, पुनरावृत्तियों और इसी तरह के लिए समर्थन प्रदान करता है ... फिर सादे मॉक का क्या कारण है ? नहीं है कि सिर्फ MagicMock के एक नीचे छीन संस्करण है कि व्यावहारिक रूप से नजरअंदाज किया जा सकता है? क्या मॉक क्लास किसी भी ट्रिक्स को जानता है जो मैजिकमॉक में उपलब्ध नहीं है ?

जवाबों:


99

प्लेन मॉक मौजूदा का क्या कारण है ?

मॉक के लेखक, माइकल फॉर्ड, ने पायकोन 2011 (31:00) में एक बहुत ही समान प्रश्न को संबोधित किया :

प्रश्न: मैजिकमॉक को डिफ़ॉल्ट मॉक ऑब्जेक्ट में क्षमता को मोड़ने के बजाय एक अलग चीज क्यों बनाया गया?

एक: एक उचित जवाब यह है कि जिस तरह से मैजिकमॉक काम करता है वह यह है कि यह सभी प्रोटोकॉल विधियों को नए मोक्स बनाकर उन्हें स्थापित करता है, इसलिए यदि हर नए नकली ने नए नकली का एक गुच्छा बनाया और उन्हें प्रोटोकॉल विधियों और फिर उन सभी प्रोटोकॉल के रूप में सेट करें। तरीकों ने एक झुंड को अधिक नकली बना दिया और उन्हें अपने प्रोटोकॉल के तरीकों पर सेट किया, आपको असीम पुनरावर्तन मिला है ...

क्या होगा यदि आप एक त्रुटि के रूप में एक कंटेनर वस्तु के रूप में अपने नकली तक पहुंचना चाहते हैं - आप नहीं चाहते कि काम करें? यदि प्रत्येक मॉक को स्वचालित रूप से प्रत्येक प्रोटोकॉल विधि मिल गई है, तो ऐसा करना अधिक कठिन हो जाता है। और भी, मैजिकमॉक आपके लिए कुछ प्री-कॉन्फिग्यूरिंग करता है, रिटर्न वैल्यू सेट करना जो कि उचित नहीं हो सकता है, इसलिए मैंने सोचा कि इस सुविधा को रखना बेहतर होगा, जिसमें आपके लिए सब कुछ प्री-कॉन्फिगर्ड और उपलब्ध हो, लेकिन आप एक साधारण नकली भी ले सकते हैं ऑब्जेक्ट और सिर्फ उन जादुई विधियों को कॉन्फ़िगर करें जिन्हें आप अस्तित्व में लाना चाहते हैं ...

इसका सरल उत्तर है: यदि आप चाहते हैं कि व्यवहार में सिर्फ मैजिकमॉक का उपयोग करें।


12
मुझे लगता है कि एक बेहतर उत्तर है: मैजिकमॉक का उपयोग करें यदि आप जानते हैं कि आप क्या कर रहे हैं, अन्यथा मॉक का उपयोग करें।
laike9m

56

मॉक के साथ आप जादू के तरीकों का मजाक उड़ा सकते हैं लेकिन आपको उन्हें परिभाषित करना होगा। मैजिकमॉक में "अधिकांश जादुई विधियों का डिफ़ॉल्ट कार्यान्वयन है।"

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


यकीन है कि मैं पहले से ही प्रलेखन पढ़ा है। कि मेरे सवाल का जवाब नहीं है - क्यों मैजिक के साथ परेशान अगर MagicMock बिल्कुल एक ही प्लस अधिक करता है? मुझे अपने परीक्षणों में कोई बाहरी चीज़ नहीं दिख रही है - बस अलग नाम का उपयोग करें और यही वह है। तो पकड़ कहां है?
व्लादिमीर इग्नाटोव

39
परीक्षण न्यूनतम होना चाहिए और नकली वस्तुएं न्यूनतम कार्यात्मक होनी चाहिए ताकि आप सुनिश्चित हों कि आप परीक्षण कर रहे हैं। यदि आप मैजिकमॉक का उपयोग सिर्फ इसलिए करते हैं कि आप अधिक कर रहे हैं, लेकिन आप स्पष्ट रूप से उन सभी "अधिक" का परीक्षण नहीं कर रहे हैं, जो कि एक डिफॉल्ट मैजिकमॉक व्यवहार के कारण आपको परीक्षण में असफल होने का खतरा है। यह विफलता मैजिकमॉक की चूक के बारे में कुछ प्रतिबिंबित कर सकती है, यह उस चीज़ से अधिक है जो नकली होना चाहिए। इससे भी बदतर, आप एक परीक्षण के सफल होने का जोखिम चलाते हैं जब इसे विफल होना चाहिए था। जोखिम छोटा है लेकिन अगर ऐसा होता है तो इससे आपका काफी समय बर्बाद होगा।
सीन रेडमंड

1
मुझे लगता है कि यह सादे जेएस बनाम जेकरी का उपयोग करने जैसा है। निश्चित रूप से, आप अपने सभी JS को करने के लिए Jquery का उपयोग कर सकते हैं, लेकिन कुछ मामलों में, आप बस काम पाने के लिए आवश्यक अति न्यूनतम उपकरण का उपयोग करना चाहते हैं। मुझे लगता है कि वे मामले आमतौर पर या तो बेहद सरल या अत्यंत जटिल होते हैं।
snuggles

49

के साथ शुरू करने के लिए, MagicMockएक उपवर्ग है Mock

class MagicMock(MagicMixin, Mock)

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

दूसरे, मैजिकमॉक कई / अधिकांश जादू विधियों के डिफ़ॉल्ट कार्यान्वयन प्रदान करता है, जबकि मॉक नहीं करता है। प्रदान किए गए जादू के तरीकों के बारे में अधिक जानकारी के लिए यहां देखें ।

प्रदान किए गए जादू के तरीकों के कुछ उदाहरण:

>>> int(Mock())
TypeError: int() argument must be a string or a number, not 'Mock'
>>> int(MagicMock())
1
>>> len(Mock())
TypeError: object of type 'Mock' has no len()
>>> len(MagicMock())
0

और ये जो उतने सहज नहीं हो सकते (कम से कम मेरे लिए सहज नहीं):

>>> with MagicMock():
...     print 'hello world'
...
hello world
>>> MagicMock()[1]
<MagicMock name='mock.__getitem__()' id='4385349968'>

मैजिकमॉक में जोड़े गए तरीकों को आप "देख" सकते हैं क्योंकि वे तरीके पहली बार लागू किए गए हैं:

>>> magic1 = MagicMock()
>>> dir(magic1)
['assert_any_call', 'assert_called_once_with', ...]
>>> int(magic1)
1
>>> dir(magic1)
['__int__', 'assert_any_call', 'assert_called_once_with', ...]
>>> len(magic1)
0
>>> dir(magic1)
['__int__', '__len__', 'assert_any_call', 'assert_called_once_with', ...]

तो, हर समय मैजिकमॉक का उपयोग क्यों न करें?

आपके लिए सवाल यह है: क्या आप डिफ़ॉल्ट मैजिक पद्धति के कार्यान्वयन के साथ ठीक हैं? उदाहरण के लिए, क्या mocked_object[1]त्रुटि नहीं करना ठीक है ? क्या जादू पद्धति लागू होने के कारण आप पहले से ही किसी अनपेक्षित परिणाम के साथ ठीक हैं?

यदि इन सवालों का जवाब हाँ है, तो आगे बढ़ें और मैजिकमॉक का उपयोग करें। अन्यथा, मॉक से चिपके रहें।


12

यह अजगर का आधिकारिक दस्तावेज क्या कहता है:

इनमें से अधिकांश उदाहरणों में मॉक और मैजिकमॉक कक्षाएं विनिमेय हैं। जैसा कि मैजिकमॉक अधिक सक्षम वर्ग है, यह डिफ़ॉल्ट रूप से उपयोग करने के लिए एक समझदार बनाता है।


3

मुझे एक और विशेष मामला मिल गया है, जहाँ साधारण Mock इससे अधिक उपयोगी हो सकता है MagicMock:

In [1]: from unittest.mock import Mock, MagicMock, ANY
In [2]: mock = Mock()
In [3]: magic = MagicMock()
In [4]: mock.foo == ANY
Out[4]: True
In [5]: magic.foo == ANY
Out[5]: False

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

यदि आप उपयोग कर रहे हैं तो यह मान्य होगा Mock:


self.assertDictEqual(my_dict, {
  'hello': 'world',
  'another': ANY
})

AssertionErrorयदि आपने उपयोग किया है तो यह बढ़ेगाMagicMock

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.