RSpec में मॉक क्या है?
(या सामान्य रूप से मॉक, क्योंकि यह अवधारणा RSpec के लिए अद्वितीय नहीं है।)
मॉक टेस्टिंग के लिए उपयोग किया जाने वाला एक ऑब्जेक्ट है।
आप दो ऑब्जेक्ट्स के बीच इंटरैक्शन का परीक्षण करने के लिए मॉक्स का उपयोग करते हैं। नियमित अपेक्षा की तरह आउटपुट मान का परीक्षण करने के बजाय।
उदाहरण के लिए:
आप एक API लिख रहे हैं जो इमेजेज को फ्लिप करता है।
अपना खुद का इमेज-मैनिपुलेशन कोड लिखने के बजाय आप mini_magick जैसे जेम का उपयोग करते हैं।
आप अपने कोड और इस बाहरी निर्भरता के बीच इंटरैक्शन का परीक्षण करना चाहते हैं... इसलिए आप एक मॉक लिखते हैं जो ImageProcessor क्लास पर सही मेथड्स के कॉल होने की अपेक्षा करता है।
इसका मतलब है कि आप हर बार अपने टेस्ट चलाने पर इमेजेज फ्लिप नहीं करेंगे (एक धीमा ऑपरेशन)।
यह कैसे काम करता है?
मॉक्स मूल ऑब्जेक्ट को प्रतिस्थापित करते हैं, इसलिए वास्तविक मेथड्स नहीं कॉल किए जाएंगे।
कुछ कोड उदाहरणों का समय!
RSpec मॉक उदाहरण
यहां ImageFlipper टेस्ट है:
RSpec.describe "ImageFlipper" do it "calls the flip method with the correct arguments" do mock = double("mini_magick") expect(mock).to receive(:flip).with("ruby.jpg") img = ImageFlipper.new(mock) img.flip("ruby.jpg") end end
इस टेस्ट के साथ हम TDD का उपयोग करके अपना कोड लिख सकते हैं।
पहले:
हमें एक ImageFlipper क्लास लिखने की आवश्यकता है।
इस तरह:
class ImageFlipper def initialize(image_processor) @image_processor = image_processor end end
हमें एक flip मेथड भी चाहिए:
def flip(file_name) end
अब हमें RSpec से यह प्रतिक्रिया मिलती है:
Failures: 1) ImageFlipper calls the flip method with the correct arguments Failure/Error: expect(mock).to receive(:flip).with("ruby.jpg") (Double "mini_magick").flip("ruby.jpg") expected: 1 time with arguments: ("ruby.jpg") received: 0 times # ./rspec-mocks.rb:6:in `block (2 levels) in <top (required)>'
यह कह रहा है कि flip मेथड को 0 बार कॉल किया गया था, लेकिन इसकी अपेक्षा 1 बार थी।
आप इसे वह देकर टेस्ट पास कर सकते हैं जो यह चाहता है:
def flip(file_name) @image_processor.flip(file_name) end
और वहां आपके पास है, हमारे पास एक पासिंग टेस्ट है:
. Finished in 0.00751 seconds (files took 0.11157 seconds to load) 1 example, 0 failures
आइए समीक्षा करें: हमने यहां क्या किया?
हमने एक ImageFlipper क्लास बनाई जो एक image_processor लेती है।
यह प्रोसेसर flip मेथड का जवाब देता है।
हम यह टेस्ट करने के लिए मॉक का उपयोग करते हैं कि क्या इस मेथड को एक बार, एक आर्गुमेंट के साथ कॉल किया गया था।
मुझे पता है।
यह उदाहरण सरल है।
लेकिन आप ImageFlipper के पूर्ण कार्यान्वयन की कल्पना कर सकते हैं जो जांचता है कि फाइल मौजूद है, यह एक वैध इमेज है, आदि।
मॉक और वैल्यू टेस्टिंग के बीच अंतर
एक नियमित टेस्ट में आप मेथड के रिटर्न मान की जांच करते हैं:
"क्या इस मेथड ने एक फ्लिप की हुई इमेज वापस की?"
मॉक का उपयोग करते समय आप व्यवहार का परीक्षण कर रहे हैं:
"क्या हमने दूसरों को सही काम करने के लिए कहा, सही जानकारी के साथ, और ठीक उतनी बार जितनी हमें जरूरत है?"
मॉक्स बनाम स्टब्स
एक और भ्रम बिंदु मॉक्स और स्टब्स की तुलना के बारे में है।
अंतर क्या है?
- स्टब केवल एक पूर्वनिर्धारित प्रतिक्रिया वाला मेथड है, यह व्यवहार की परवाह नहीं करता।
- मॉक मेथड्स के कॉल होने की अपेक्षा करता है, यदि वे कॉल नहीं किए जाते तो टेस्ट फेल हो जाएगा।
यहां RSpec में एक स्टब है:
stub = double("json") allow(stub).to receive(:response) do {"blog"=>"rubyguides.com", "rating"=>"5/5"}.to_json end
allow मेथड इसे स्टब बनाता है।
हम अपने टेस्ट ऑब्जेक्ट double("json") को इस मेथड को प्राप्त करने और प्रतिक्रिया देने की अनुमति दे रहे हैं, लेकिन हम यह जांच नहीं कर रहे हैं कि इसे कॉल किया जा रहा है।
यही अंतर है!
सत्यापित डबल्स का उपयोग कैसे करें
मॉक्स और स्टब्स के नुकसानों में से एक यह है कि आप अपने प्रोडक्शन कोड में मौजूद नहीं मेथड का उपयोग कर सकते हैं।
क्योंकि मेथड का नाम बदल गया है... या शायद आपने टाइपो कर दिया!
मिलिए सत्यापित डबल्स से।
एक सत्यापित डबल का उपयोग या तो स्टब (allow) या मॉक (expect) के रूप में किया जा सकता है और यह जांच करेगा कि इस नाम का कोई मेथड मौजूद है।
उदाहरण:
mock = instance_double(ImageProcessor)
यदि मेथड मौजूद नहीं है तो यह एक त्रुटि उठाएगा:
1) ImageFlipper calls the flip method with the correct arguments Failure/Error: expect(mock).to receive(:flip).with("ruby.jpg") the ImageProcessor class does not implement the instance method: flip
लेकिन यह सही ढंग से काम करेगा यदि मेथड मौजूद है।
मॉक्स मान वापस करना
आइए मॉकिंग पर वापस चलते हैं।
पिछले उदाहरण में हमारे पास यह था:
expect(mock).to receive(:flip).with("ruby.jpg")
जब आपका कोड flip कॉल करता है, तो मॉक nil वापस करेगा।
यदि कोड nil के अलावा कुछ मान की अपेक्षा कर रहा है तो इसके परिणामस्वरूप त्रुटि होगी।
आप मॉक को परिणाम वापस करके इसे ठीक कर सकते हैं।
इस तरह:
expect(mock).to receive(:flip).with("ruby.jpg").and_return("ruby-flipped.jpg")
इंस्टेंस मेथड्स को मॉक कैसे करें
मान लीजिए कि आपके पास ऐसा कोड है:
class NumberGenerator def random "A" * rand(1..10) end end
इस मेथड का परीक्षण करना मुश्किल है क्योंकि रैंडमनेस के कारण।
RSpec आपको rand को मॉक या स्टब करने की अनुमति देता है।
इस तरह:
it "generates a random number" do generator = NumberGenerator.new allow(generator).to receive(:rand).and_return(5) expect(generator.random).to eq("AAAAA") end
अब:
rand एक निश्चित मान लौटाता है ताकि आप इसका उपयोग अपने मेथड के परिणाम का परीक्षण करने के लिए कर सकें।
आदर्श रूप से, आप अपनी निर्भरता को इंजेक्ट करना चाहेंगे (इस मामले में rand फ़ंक्शन) ताकि आप इसे नियंत्रित कर सकें। निर्भरता इंजेक्ट करने का मतलब है कि आप इसे पैरामीटर के रूप में पास करते हैं, कुछ फैंसी नहीं।
लेकिन कभी-कभी मेथड को स्टब करना अधिक सुविधाजनक होता है।
मॉक्स का उपयोग कब करें?
अब बड़े सवाल के लिए...
वास्तव में आपको मॉक्स का उपयोग कब करना चाहिए?
सॉफ्टवेयर विकास एक जटिल विषय है।
लेकिन कुछ दिशानिर्देश हैं जिनका आप पालन कर सकते हैं:
- यदि टेस्ट के तहत मेथड एक मान लौटाता है और इसका कोई साइड इफेक्ट नहीं है (फाइल बनाना, API रिक्वेस्ट करना, आदि) तो आपको मॉक की आवश्यकता नहीं है। बस रिटर्न मान की जांच करें।
- यदि मेथड बाहरी ऑब्जेक्ट्स के साथ काम कर रहा है और उन्हें ऑर्डर भेज रहा है, तो आप इन ऑब्जेक्ट्स के साथ इंटरैक्शन को मॉक कर सकते हैं।
- यदि मेथड किसी बाहरी सेवा से डेटा का अनुरोध कर रहा है (जैसे API), तो आप टेस्टिंग उद्देश्यों के लिए इस डेटा को प्रदान करने के लिए स्टब का उपयोग कर सकते हैं।
आप बाहरी दुनिया के साथ इंटरैक्शन के लिए मॉकिंग को आरक्षित करना चाहते हैं।
दूसरे शब्दों में...
अपने स्वयं के एप्लिकेशन की क्लासेज को मॉक करने से बचें!
क्यों?
क्योंकि यह आपके टेस्ट्स को कार्यान्वयन विवरणों के साथ जोड़ता है और आपके कोड को बदलना कठिन बना देता है।
एकमात्र अपवाद उन क्लासेज के लिए है जो थर्ड-पार्टी कोड के लिए रैपर हैं।
अधिक जानने के लिए यह वीडियो देखें:
सारांश
आपने RSpec मॉक्स, स्टब्स और सत्यापित डबल्स के बारे में सीखा!
कृपया इस लेख को साझा करें ताकि अधिक लोग इसका आनंद ले सकें और इससे लाभ उठा सकें।
पढ़ने के लिए धन्यवाद 🙂