2011-07-28 3 views
5

मैं I1 से ILogger इस तरह कार्यान्वित करने के लिए एडॉप्टर है:बिना किसी कोड के एडाप्टर के लिए जुनीट कैसे लिखें?

class BAdapter() implements I1 
{ 
    void logA() { // nothing } 
    void logB() { new BLogger().log() } 
    void logC() { // nothing } 
} 

मैं JUnit परीक्षण लिखने के लिए चाहते हैं, कि कार्यक्षमता को सत्यापित, लेकिन मैं, यह थोड़ा समस्यापूर्ण लगी के बाद से मैं अपने नकली वस्तु के बजाय इंजेक्षन नहीं कर सकते BLogger का, या वापसी मूल्य सत्यापित करें। मुझे कई संभावित समाधान मिले, लेकिन मुझे यकीन नहीं है, जो सबसे अच्छा है।

केस एक: BAdapter वर्ग के लिए void setLogger(Logger l) जोड़ें।

class BAdapter() implements I1 
{ 
    private Logger logger = new BLogger(); 

    public void logB() { logger.log() } 
    public void setLogger(Logger l) { logger = l } 
    .. //rest of methods 
} 

विपक्ष: क्यों सेटर जोड़ने के लिए जिसका उपयोग कभी भी "असली", गैर-परीक्षण कोड में नहीं किया जाता है?

केस दो: जोड़ें संरक्षित कारखाने विधि और परीक्षण पैकेज में sublcass BAdapter

class BAdapter() implements I1 
{ 
    public void logB() { createLogger().log() } 
    protected Logger createLogger() { retrun new BLogger() } 
    .. //rest of methods 
} 

class BAdapterForTesting extends BAdapter() 
{ 
    protected Logger createLogger() { retrun new MockBLogger() } 
} 

विपक्ष: मुझे यकीन नहीं है, अगर यह साफ और सुरुचिपूर्ण समाधान है, लेकिन मुझे यहां बहुत अधिक विपक्ष नहीं दिख रहा है।

केस तीन: सार फैक्टरी पैटर्न का उपयोग करें।

class BAdapter() implements I1 
{ 
    public void logB() { AbstractFactory.getFactory().getBLogger().log() } 
    .. //rest of methods 
} 

और कहीं परीक्षणों में:

AbstractFactory.setFactory(new MockLoggersFactory()) 

विपक्ष: यह बहुत जटिल है, है ना?

केस चार: रिटर्न बूलियन, उदाहरण के लिए, जब लॉगिंग किया गया था। जैसे

class BAdapter() implements I1 
{ 
    Boolean logA() { return false; } 
    Boolean logB() { return new BLogger().log() } 
    Boolean logC() { return false; } 
} 

विपक्ष: यह एक प्रकार का घाटा है। कुछ मूल्य वापस क्यों करें, जब किसी को इसे "वास्तविक", गैर परीक्षण कोड में क्यों चाहिए?

बेहतर समाधान? क्या कुछ बेहतर है?

उत्तर

2

अपने कोड से यह कहना मुश्किल है कि परीक्षा के तहत कक्षा क्या हासिल करने की कोशिश कर रही है लेकिन मैं केस वन के साथ इस चेतावनी के साथ जाऊंगा कि मैं 'वास्तविक' कोड में भी इंजेक्शन का उपयोग करूंगा।

इंजेक्शन के लाभों में से एक यह वर्ग बनाता है, इस मामले में आपका एडाप्टर, अधिक पुनः उपयोग करने योग्य। logB विधि को हमेशा BLogger के उदाहरण के लिए प्रतिनिधि करने के लिए मजबूर करना संकलन समय पर पत्थर में व्यवहार को सेट करता है। अगर मैं एडाप्टर को किसी अन्य प्रकार के Logger पर प्रतिनिधि करना चाहता हूं तो मैं इसका उपयोग नहीं कर सकता और इसलिए यह थोड़ा कम उपयोग करने योग्य है।

+0

मुझे एक्शन बुक में जुनीट में समान दृष्टिकोण मिला। परीक्षण कोड आपके कोड का क्लाइंट किसी अन्य के रूप में है, इसलिए यूनिट परीक्षण आवश्यकताओं के अनुरूप कोड को पुन: कारक या अपडेट करना अच्छा होता है। –

0

IMVHO विशेष रूप से परीक्षणों द्वारा उपयोग किए जाने वाले कोड बनाने के लिए और कहीं और नहीं, यह एक अच्छा विचार नहीं है क्योंकि यह कार्यक्षमता का पर्दाफाश कर सकता है जिसका उपयोग नहीं किया जाना चाहिए, फिर भी कुछ सोच सकते हैं कि इसका उपयोग करना अच्छा है और बुरी तरह आश्चर्यचकित हो।

यह हमें 3 मामले के साथ छोड़ देता है जो आम तौर पर बहुत अच्छा दृष्टिकोण है, फिर भी इसका उपयोग केवल थोड़ी अधिक ओवरकिल के परीक्षण के दौरान किया जाना है।

मैं PowerMock जैसे कुछ अतिरिक्त मजाक ढांचे सुविधाजनक तरीके से कक्षाओं में निजी क्षेत्रों को बदल सकते हैं उपयोग करने का सुझाव चाहते हैं:

class BAdapter() implements I1 
{ 
    private Logger logger = new BLogger(); 

    public void logB() { logger.log() } 
    .. //rest of methods 
} 

और फिर कुछ नकली करने के लिए स्वैप क्षेत्र परीक्षण के दौरान:

Whitebox.setInternalState(loggerInstance, "logger", new MockLogger()); 

अधिक जानकारी: http://code.google.com/p/powermock/wiki/BypassEncapsulation

मॉकिंग फ्रेमवर्क परीक्षण के दौरान बड़ी संपत्ति हैं ताकि उन्हें मदद मिल सके बहुत कुछ है