जावा में परीक्षण: मॉड्यूलर से एंड-टू-एंड टेस्ट तक
कोड की गुणवत्ता डेवलपर की व्यावसायिकता के मुख्य संकेतकों में से एक है। जावा की दुनिया में, परीक्षण लंबे समय से केवल एक अच्छी प्रथा नहीं, बल्कि उद्योग का मानक बन गया है। विश्वसनीय परीक्षणों के बिना बड़े प्रोजेक्ट्स को बनाए रखना, नई सुविधाएँ जोड़ना और आत्मविश्वास से कोड को रिफैक्टर करना मुश्किल है। इस लेख में, हम परीक्षण के तीन प्रमुख स्तरों पर चर्चा करेंगे: unit (मॉड्यूलर), integration (एकीकरण) और e2e (एंड-टू-एंड)। आप जानेंगे कि वे कैसे भिन्न हैं, उन्हें जावा में सही तरीके से कैसे लिखें और किन टूल्स का उपयोग करें।
परीक्षण पिरामिड और यह क्यों महत्वपूर्ण है
विवरण में जाने से पहले, परीक्षण पिरामिड (Mike Cohn) की अवधारणा को याद करना उचित है। यह विभिन्न स्तरों के परीक्षणों के आदर्श अनुपात को दर्शाता है:
- यूनिट-टेस्ट (पिरामिड का आधार) — सबसे तेज़, सस्ते और अधिक संख्या में। इनकी संख्या लगभग 70% होनी चाहिए।
- इंटीग्रेशन-टेस्ट (मध्य) — घटकों के बीच बातचीत की जाँच करते हैं। इनकी संख्या लगभग 20% है।
- ई2ई-टेस्ट (शीर्ष) — सबसे धीमे और महंगे, लेकिन उपयोगकर्ता परिदृश्यों की जाँच के लिए महत्वपूर्ण हैं। इनकी संख्या लगभग 10% है।
इस अनुपात का पालन करने से परीक्षण चलाने में न्यूनतम समय खर्च करते हुए कोड में अधिकतम विश्वास प्राप्त किया जा सकता है।
1. जावा में यूनिट-टेस्टिंग
यूनिट-टेस्ट कोड के एक "यूनिट" — आमतौर पर एक मेथड या क्लास — को अलग-थलग करके जाँचते हैं। इनका मुख्य उद्देश्य यह सुनिश्चित करना है कि मेथड का लॉजिक बाहरी निर्भरताओं (डेटाबेस, API, फ़ाइल सिस्टम) से स्वतंत्र रूप से सही ढंग से काम करता है। अलगाव के लिए mock-ऑब्जेक्ट्स का उपयोग किया जाता है।
मुख्य उपकरण
- JUnit 5 — टेस्ट लिखने के लिए मानक फ्रेमवर्क।
- Mockito — mock-ऑब्जेक्ट्स बनाने और इंटरैक्शन की जाँच के लिए लाइब्रेरी।
- AssertJ — fluent-असर्ट के लिए लाइब्रेरी (पठनीयता बढ़ाता है)।
JUnit 5 और Mockito के साथ यूनिट-टेस्ट का उदाहरण
मान लीजिए, हमारे पास एक सेवा UserService है जो UserRepository पर निर्भर करती है:
public class UserService { private final UserRepository repository; public UserService(UserRepository repository) { this.repository = repository; } public User findById(Long id) { return repository.findById(id) .orElseThrow(() -> new UserNotFoundException("User not found")); }}इस मेथड के लिए टेस्ट:
import org.junit.jupiter.api.Test;import org.junit.jupiter.api.extension.ExtendWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.junit.jupiter.MockitoExtension;import java.util.Optional;import static org.junit.jupiter.api.Assertions.*;import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)class UserServiceTest {
@Mock private UserRepository repository;
@InjectMocks private UserService userService;
@Test void testFindById_UserExists() { // Given Long userId = 1L; User expectedUser = new User(userId, "Alice"); when(repository.findById(userId)).thenReturn(Optional.of(expectedUser));
// When User actualUser = userService.findById(userId);
// Then assertNotNull(actualUser); assertEquals("Alice", actualUser.getName()); verify(repository).findById(userId); }
@Test void testFindById_UserNotFound() { // Given Long userId = 99L; when(repository.findById(userId)).thenReturn(Optional.empty());
// When & Then assertThrows(UserNotFoundException.class, () -> userService.findById(userId)); }}Best practices:
- एक