मुझे हमेशा इसे बार-बार देखना पड़ता है, इसलिए यहां मेरा जवाब है।
एक ही वर्ग के विभिन्न ऑब्जेक्ट्स पर कई विधि कॉल करना
मान लें कि हमारे पास एक भारी शुल्क वर्ग है (जिसे हम मॉक करना चाहते हैं):
In [1]: class HeavyDuty(object):
...: def __init__(self):
...: import time
...: time.sleep(2) # <- Spends a lot of time here
...:
...: def do_work(self, arg1, arg2):
...: print("Called with %r and %r" % (arg1, arg2))
...:
यहाँ कुछ कोड है जो HeavyDuty
कक्षा के दो उदाहरणों का उपयोग करता है :
In [2]: def heavy_work():
...: hd1 = HeavyDuty()
...: hd1.do_work(13, 17)
...: hd2 = HeavyDuty()
...: hd2.do_work(23, 29)
...:
अब, यहाँ heavy_work
फ़ंक्शन के लिए एक परीक्षण मामला है :
In [3]: from unittest.mock import patch, call
...: def test_heavy_work():
...: expected_calls = [call.do_work(13, 17),call.do_work(23, 29)]
...:
...: with patch('__main__.HeavyDuty') as MockHeavyDuty:
...: heavy_work()
...: MockHeavyDuty.return_value.assert_has_calls(expected_calls)
...:
हम HeavyDuty
वर्ग के साथ मजाक कर रहे हैं MockHeavyDuty
। प्रत्येक HeavyDuty
उदाहरण से आने वाली विधि कॉलों का दावा करने के लिए MockHeavyDuty.return_value.assert_has_calls
, हमें इसके बजाय संदर्भित करना होगा MockHeavyDuty.assert_has_calls
। इसके अलावा, expected_calls
हमें सूची में यह निर्दिष्ट करना होगा कि हम किस विधि के नाम पर कॉल करने के लिए रुचि रखते हैं। तो हमारी सूची कॉल के लिए बनी है call.do_work
, जैसा कि बस के विपरीत है call
।
परीक्षण मामले का अभ्यास करने से हमें पता चलता है कि यह सफल है:
In [4]: print(test_heavy_work())
None
यदि हम heavy_work
फ़ंक्शन को संशोधित करते हैं, तो परीक्षण विफल हो जाता है और एक उपयोगी त्रुटि संदेश उत्पन्न करता है:
In [5]: def heavy_work():
...: hd1 = HeavyDuty()
...: hd1.do_work(113, 117) # <- call args are different
...: hd2 = HeavyDuty()
...: hd2.do_work(123, 129) # <- call args are different
...:
In [6]: print(test_heavy_work())
---------------------------------------------------------------------------
(traceback omitted for clarity)
AssertionError: Calls not found.
Expected: [call.do_work(13, 17), call.do_work(23, 29)]
Actual: [call.do_work(113, 117), call.do_work(123, 129)]
एक फ़ंक्शन में कई कॉल करने का दावा करना
उपरोक्त के साथ विपरीत करने के लिए, यहां एक उदाहरण दिया गया है जो दिखाता है कि फ़ंक्शन में कई कॉल को कैसे मॉक करें:
In [7]: def work_function(arg1, arg2):
...: print("Called with args %r and %r" % (arg1, arg2))
In [8]: from unittest.mock import patch, call
...: def test_work_function():
...: expected_calls = [call(13, 17), call(23, 29)]
...: with patch('__main__.work_function') as mock_work_function:
...: work_function(13, 17)
...: work_function(23, 29)
...: mock_work_function.assert_has_calls(expected_calls)
...:
In [9]: print(test_work_function())
None
दो मुख्य अंतर हैं। पहली बात यह है कि जब हम किसी फंक्शन का मखौल उड़ाते हैं तो हम इस्तेमाल call
करने के बजाय अपनी अपेक्षित कॉल का इस्तेमाल करते हैं call.some_method
। दूसरा एक है कि हम कहते हैं assert_has_calls
पर mock_work_function
बजाय पर की, mock_work_function.return_value
।