बिना Mock ऑब्जेक्ट के टेस्ट करना, बिना नमक का खाना पकाने जैसा है
\n\nकल्पना करें कि आप एक ऐसा ऐप लिख रहे हैं जो ईमेल नोटिफिकेशन भेजता है, डेटाबेस के साथ काम करता है, और किसी तीसरे पक्ष के API का उपयोग करता है। PHP में mock ऑब्जेक्ट और fixtures के बिना आप इसका परीक्षण कैसे करेंगे? आपको हर बार असली ईमेल भेजने होंगे, डेटाबेस में टेस्ट रिकॉर्ड बनाने होंगे, और बाहरी सेवा से जवाब का इंतजार करना होगा। यह धीमा, अविश्वसनीय और बिल्कुल बेवकूफी है।
\n\nयहाँ पर test doubles काम आते हैं - ये असली ऑब्जेक्ट के विकल्प होते हैं। PHP इकोसिस्टम में इसके लिए दो चीजों का उपयोग किया जाता है: मॉक ऑब्जेक्ट (mock) इंटरैक्शन की जांच के लिए और फिक्स्चर (fixtures) डेटा तैयार करने के लिए। आइए व्यवहार में समझते हैं कि यह कैसे काम करता है।
\n\nMock vs Stub vs Fake: गलती न करें
\n\nकोड में गोता लगाने से पहले, बातों को स्पष्ट कर लेते हैं। PHP यूनिट टेस्टिंग की दुनिया में तीन मुख्य प्रकार के विकल्प हैं:
\n\n- \n
- Stub (स्टब) - पहले से तय डेटा लौटाता है। आप जांचते हैं कि आपका कोड इस डेटा को सही तरीके से प्रोसेस कर रहा है या नहीं। \n
- Mock (मॉक) - न सिर्फ डेटा लौटाता है, बल्कि यह भी जांचता है कि आपका सिस्टम मेथड को कैसे कॉल कर रहा है: कितनी बार, किन आर्गुमेंट्स के साथ, किस क्रम में। \n
- Fake (फेक) - एक सरलीकृत कार्यशील इम्प्लीमेंटेशन (जैसे, in-memory डेटाबेस)। \n
PHPUnit में, जो PHP टेस्टिंग का डी-फैक्टो स्टैंडर्ड है, इन अवधारणाओं को अक्सर मिला दिया जाता है। लेकिन हम सटीक रहेंगे: PHP में mock ऑब्जेक्ट वे हैं जहाँ आप अपेक्षाएँ (expectations) सेट करते हैं।
\n\nPHPUnit पर पहला mock ऑब्जेक्ट लिखना
\n\nमान लीजिए हमारे पास एक Mailer क्लास है जो ईमेल भेजता है। हम यह जांचना चाहते हैं कि रजिस्ट्रेशन सर्विस send() मेथड को सही डेटा के साथ ठीक एक बार कॉल करता है या नहीं।
<?php\nuse PHPUnit\\Framework\\TestCase;\n\nclass UserRegistrationTest extends TestCase\n{\n public function testSendWelcomeEmailOnRegistration(): void\n {\n // Mailer के लिए mock बनाएँ\n $mailer = $this->createMock(Mailer::class);\n \n // अपेक्षा सेट करें: send मेथड 1 बार कॉल होगा\n $mailer->expects($this->once())\n ->method('send')\n ->with(\n $this->equalTo('user@example.com'),\n $this->stringContains('Welcome')\n );\n \n $service = new UserRegistrationService($mailer);\n $service->register('user@example.com', 'password123');\n }\n}\n\n\nध्यान दें: हम यह नहीं जांच रहे कि ईमेल वास्तव में गया है। हम जांच रहे हैं कि हमारे कोड ने इसे भेजने का प्रयास किया - यही PHP टेस्ट में mock ऑब्जेक्ट का सार है। अगर send() मेथड कॉल नहीं होता (या दो बार होता है), तो टेस्ट फेल हो जाएगा।
expects मेथड और इसकी क्षमताएँ
\n\nPHPUnit अपेक्षाएँ सेट करने के लिए एक समृद्ध API प्रदान करता है:
\n\n- \n
$this->once()- बिल्कुल एक कॉल \n $this->exactly(3)- बिल्कुल तीन कॉल \n $this->atLeastOnce()- कम से कम एक कॉल \n $this->never()- मेथड कॉल नहीं होना चाहिए \n
आर्गुमेंट्स के लिए मैचर्स (constraints) का उपयोग करें:
\n\n$mailer->expects($this->once())\n ->method('send')\n ->with(\n $this->callback(function($email) {\n return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;\n }),\n $this->anything() // हमें दूसरे आर्गुमेंट से कोई फर्क नहीं पड़ता\n );\n\n\nPHP में Fixtures: ज़रूरत से पहले डेटा तैयार करें
\n\nFixtures डेटा की पूर्व-निर्धारित स्थिति है जिसमें टेस्ट चलाने से पहले सिस्टम होता है। PHPUnit में इसके लिए setUp() और