कारणों में से एक परीक्षण क्षमता है। कहो कि आपके पास यह वर्ग है:
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
@Component
class MyBean {
@Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
आप इस बीन का परीक्षण कैसे कर सकते हैं? इस तरह:
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
आसान है, है ना?
यद्यपि आप अभी भी स्प्रिंग पर निर्भर हैं (एनोटेशन के कारण) आप किसी भी कोड (केवल एनोटेशन परिभाषाओं) को बदलने के बिना वसंत पर निर्भरता को दूर कर सकते हैं और परीक्षण डेवलपर को कुछ भी जानने की आवश्यकता नहीं है कि वसंत कैसे काम करता है (शायद वह वैसे भी, लेकिन यह स्प्रिंग को अलग से कोड की समीक्षा और परीक्षण करने की अनुमति देता है)।
ApplicationContext का उपयोग करते समय भी ऐसा करना संभव है। हालाँकि तब आपको मज़ाक करने की ज़रूरत है ApplicationContext
जो एक बहुत बड़ा इंटरफ़ेस है। आपको या तो डमी कार्यान्वयन की आवश्यकता है या आप मॉकिटो जैसे मॉकिंग फ्रेमवर्क का उपयोग कर सकते हैं:
@Component
class MyBean {
@Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
यह काफी संभावना है, लेकिन मुझे लगता है कि ज्यादातर लोग इस बात से सहमत होंगे कि पहला विकल्प अधिक सुरुचिपूर्ण है और परीक्षण को सरल बनाता है।
एकमात्र विकल्प जो वास्तव में एक समस्या है यह एक है:
@Component
class MyBean {
@Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
इसके परीक्षण के लिए भारी प्रयासों की आवश्यकता होती है या आपका बीन प्रत्येक परीक्षण के स्टैकओवरफ्लो से जुड़ने का प्रयास करने वाला होता है। और जैसे ही आपके पास एक नेटवर्क विफलता है (या स्टैकओवरफ़्लो में प्रवेश आपको अत्यधिक पहुंच दर के कारण ब्लॉक करता है) आपके पास बेतरतीब ढंग से विफल परीक्षण होंगे।
इसलिए एक निष्कर्ष के रूप में मैं यह नहीं कहूंगा कि ApplicationContext
सीधे उपयोग करना स्वचालित रूप से गलत है और इसे हर कीमत पर टाला जाना चाहिए। हालांकि अगर बेहतर विकल्प हैं (और ज्यादातर मामलों में हैं), तो बेहतर विकल्पों का उपयोग करें।
new MyOtherClass()
? मैं @Autowired के बारे में जानता हूं, लेकिन मैंने इसे कभी भी खेतों पर इस्तेमाल किया है और यह टूट जाता हैnew MyOtherClass()
..