आपके Java टेस्ट क्यों फेल होते हैं (और इसे कैसे ठीक करें)
\n\nआपने परफेक्ट कोड लिखा है। सर्विस काम कर रही है, लॉजिक बिल्कुल सही है, और बग्स सिर्फ दूसरों के प्रोजेक्ट में हैं। लेकिन जब आप टेस्ट चलाते हैं... तो कहीं डेटाबेस कनेक्शन में एरर, कहीं बाहरी API रिस्पॉन्स नहीं दे रही, और तीसरे टेस्ट में NullPointerException क्योंकि कॉन्फ़िगरेशन गलत लोड हुई। परिचित लग रहा है?
\n\nसमस्या यह है कि पारंपरिक टेस्ट बाहरी वातावरण पर निर्भर करते हैं। डेटाबेस, REST-सर्विसेज, फ़ाइल सिस्टम — ये सब टेस्ट को कमज़ोर, धीमा और अनप्रेडिक्टेबल बनाते हैं। इसका समाधान है mock-ऑब्जेक्ट और fixtures। ये सिर्फ ट्रेंडी शब्द नहीं हैं, बल्कि ऐसे टूल्स हैं जो अव्यवस्था को व्यवस्था में बदल देते हैं।
\n\nइस आर्टिकल में हम रियल उदाहरणों के साथ Java टेस्ट में mock और fixtures का सही उपयोग समझेंगे। आप जानेंगे कि stub और mock में क्या अंतर है, जटिल सीनारियो के लिए fixtures कैसे सेट करें, और क्यों Mockito आपका सबसे अच्छा दोस्त है। चलिए शुरू करते हैं!
\n\nMock-ऑब्जेक्ट: बिना दर्द के सिमुलेशन
\n\nMock क्या है और इसकी ज़रूरत क्यों है?
\n\nMock-ऑब्जेक्ट एक रियल कम्पोनेंट का नकली संस्करण है, जो आपके बताए अनुसार व्यवहार करता है। डेटाबेस चालू करने या बाहरी API कॉल करने के बजाय, आप एक "नकली" ऑब्जेक्ट बनाते हैं जो पहले से तय डेटा रिटर्न करता है।
\n\nकल्पना करें: आप एक ऐसी सर्विस टेस्ट कर रहे हैं जो ईमेल नोटिफिकेशन भेजती है। असली टेस्ट के लिए मेल सर्वर चालू करना, SMTP सेट करना, कतार चेक करना होगा... लेकिन mock-ऑब्जेक्ट से आप सिर्फ यह चेक करते हैं कि सर्विस ने सही पैरामीटर के साथ मेथड कॉल किया। तेज़, साफ, और पूरी तरह नियंत्रित।
\n\nMock vs Stub: क्या अंतर है?
\n\nनए डेवलपर्स अक्सर इन दोनों को कन्फ्यूज़ करते हैं। आइए इसे स्पष्ट करते हैं:
\n\n- \n
- Stub — फिक्स्ड डेटा रिटर्न करता है। आप कहते हैं: "जब getUser() मेथड कॉल हो, तो "John" नाम वाला User ऑब्जेक्ट लौटाओ"। Stub यह चेक नहीं करता कि उसे कितनी बार कॉल किया गया। \n
- Mock — न सिर्फ डेटा रिटर्न करता है, बल्कि व्यवहार की जांच भी करता है। आप कह सकते हैं: "पक्का करो कि sendEmail() मेथड एक विशिष्ट पते पर ठीक एक बार कॉल हुआ"। \n
सीधे शब्दों में: stub का मतलब है "मुझे डेटा दो", mock का मतलब है "मुझे डेटा दो और जांचो कि मेरा उपयोग कैसे हुआ"। व्यवहार में, ज़्यादातर mock-ऑब्जेक्ट का उपयोग होता है क्योंकि वे ज़्यादा नियंत्रण देते हैं।
\n\nMockito के साथ पहला mock लिखना
\n\nMockito Java में मॉकिंग के लिए सबसे लोकप्रिय लाइब्रेरी है। यह JUnit 5 और Spring Boot के साथ इंटीग्रेट होती है, और इसका सिंटैक्स इतना आसान है कि आप पाँच मिनट में याद कर लेंगे।
\n\nमान लीजिए, आपके पास एक सर्विस OrderService है जो रिपॉजिटरी OrderRepository पर निर्भर करती है। असली रिपॉजिटरी के बजाय हम एक mock बनाएंगे:
import static org.mockito.Mockito.*;\nimport org.junit.jupiter.api.Test;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.junit.jupiter.api.extension.ExtendWith;\n\n@ExtendWith(MockitoExtension.class)\npublic class OrderServiceTest {\n\n @Mock\n private OrderRepository orderRepository;\n\n @Test\n void testCreateOrder() {\n // mock-ऑब्जेक्ट बनाएं\n OrderService orderService = new OrderService(orderRepository);\n \n // mock का व्यवहार सेट करें\n when(orderRepository.save(any(Order.class)))\n .thenReturn(new Order(1L, "test@example.com", 100.0));\n \n // टेस्ट किए जाने वाले मेथड को कॉल करें\n Order result = orderService.createOrder("test@example.com", 100.0);\n \n // रिजल्ट चेक करें\n assertThat(result.getId()).isEqualTo(1L);\n // चेक करें कि save मेथड ठीक एक बार कॉल हुआ\n verify(orderRepository, times(1)).save(any(Order.class));\n }\n}\n\nइस उदाहरण में हमने:
\n- \n
@Mockएनोटेशन सेOrderRepositoryका mock बनाया। \n - सेट किया कि जब
save()कॉल हो, तो पहले से बनाया गया ऑर्डर रिटर्न हो। \n - चेक किया कि
save()मेथड ठीक एक बार कॉल हुआ। \n