2012-05-26 7 views
5

मैं JUnit + Mockito का उपयोग कर की तरह एक विधि का परीक्षण करने के लिए एक इकाई परीक्षण लिख रहा हूँ:सार कक्षा उपवर्गीकरण बिना एक अमूर्त वर्ग के एक सार्वजनिक विधि पर एक कॉल मजाक, mockito का उपयोग कर prefererably

public someObject methodUnderTest(){ 
    SomeObject obj = SomeAbstractClass.someMethod(); 

    if(obj!=null){ 
    obj.someOtherMethod(); 
    } 

    return someThing; 
} 

और मैं चाहते हैं abstract Class "SomeAbstractClass" ऊपर कोड टुकड़ा में उल्लेख किया है पर कॉल उपहास करने के लिए तो मैं पर "obj" की तरह कॉल की पुष्टि कर सकते हैं:

verify(SomeAbstractClass).someMethod(); 
verify(obj).someOtherMethod(); 

मैं की तरह mockito सुविधाओं का उपयोग कर की कोशिश की है: Mockito.CALLS_REAL_METHODS mockito। RETURNS_MOCKS

लेकिन वे SomeAbstractClass के लिए उपलब्ध नहीं निर्भरता की वजह से काम नहीं करते।

नोट:

1) SomeObject एक अंतरफलक है।

2) मुझे उपरोक्त कोड खंड का परीक्षण करने के लिए एक तकनीक की आवश्यकता है। मैं उपरोक्त कोड खंड का उपयोग करने के लिए बाध्य हूं और कोड खंड को बदल नहीं सकता।

उत्तर

1

धारणा: यदि आप इकाई परीक्षण लिखते हैं, मुझे लगता है कि आप अभी भी परीक्षण किया विधि थोड़ा संशोधित कर सकते हैं।

समाधान:

overridable विधि के लिए
  1. निकालने स्थिर विधि कॉल:
public someObject methodUnderTest() { 
    SomeObject obj = getSomeObject(); 

    if(obj!=null){ 
     obj.someOtherMethod(); 
    } 

    return someThing; 
} 

protected SomeObject getSomeObject() { 
    return SomeAbstractClass.someMethod(); 
} 
  1. तो आप आंशिक रूप से वस्तु आप वास्तव में परीक्षण उपहास करने के लिए Mockito जासूस का उपयोग कर सकते हैं:
private ClassUnderTest classUnderTest; 

@Before 
public void setUp() { 
    classUnderTest= new ClassUnderTest(); 
    classUnderTest = Mockito.spy(classUnderTest); 
} 

@Test 
public void test() { 
    SomeObject someObject = Mockito.mock(SomeObject.class); 
    when(classUnderTest.getSomeObject()).thenReturn(someObject); 
    classUnderTest.methodUnderTest(); 
    verify(someObject).someOtherMethod(); 
} 

@Test 
public void testNull() { 
    when(classUnderTest.getSomeObject()).thenReturn(null); 
    classUnderTest.methodUnderTest(); 
    verify(something); 
} 
+0

आपकी सहायता के लिए धन्यवाद miheys देखें। मैंने बिल्कुल वही किया। –

1

उपयोग गुमनाम कक्षाएं:

public interface SomeObject { 
    public Object someOtherMethod(); 
} 

public abstract class SomeAbstractClass { 
    abstract SomeObject someMethod(); 
} 

@Test 
public void test() { 
    SomeAbstractClass target = new SomeAbstractClass() { 
     SomeObject someMethod() { 
      // some impl 
      SomeObject someObject = new SomeObject() { 
       public Object someOtherMethod() { 
        // some other impl 
       } 
      }; 
      return someObject; 
     } 
    }; 

    // now test target 
} 
+0

धन्यवाद बोहेमियन, लेकिन मैं उल्लेख करना भूल गया SomeObject लौटे कि एक अंतरफलक के साथ-साथ "SomeAbstractClass.someMethod()" एक सार्वजनिक और स्थैतिक विधि है। इसलिए मैं इंटरफेस "SomeObject" जो मैं के रूप में करने के लिए नहीं करना चाहते, दोनों "SomeAbstractClass" और "SomeObject" को लागू करने के लिए मजबूर कर रहा हूँ जो मैं अपने वेब अनुप्रयोग में उपयोग कर रहा हूँ एक 3 पार्टी पुस्तकालय का हिस्सा हैं। –

+0

आप एक इंटरफ़ेस (जैसे SomeObject) के लिए एक अज्ञात वर्ग का भी उपयोग कर सकते हैं - संपादित उत्तर – Bohemian

2

आप PowerMock का उपयोग स्थिर और अंतिम तरीकों उपहास करने के लिए कर सकते हैं।

2

ऐसा लगता है समस्या की तरह है कि CALLS_REAL_METHODS के आपके उपयोग पूरी क्लास, जहाँ आप वास्तव में विशिष्ट विधियों बाहर नकली करना चाहते हैं के लिए आवेदन किया जाता है (अर्थात एक "आंशिक नकली" बनाओ)। आप यहाँ दो विकल्प, एक thenCallRealMethod का उपयोग कर, और एक CALLS_REAL_METHODS और उसके बाद का उपयोग कर विशेष रूप से कॉल आप की जरूरत मजाक है:

public void testMethodUnderTest_mockSpecificThings() { 
    SomeAbstractClass myAbstractClass = Mockito.mock(SomeAbstractClass.class); 
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class); 
    when(myAbstractClass.someMethod()).thenReturn(foo); 
    when(myAbstractClass.methodUnderTest()).thenCallRealMethod(); 

    myAbstractClass.methodUnderTest(); 

    verify(myAbstractClass).someMethod(); 
    verify(myObject).someOtherMethod(); 
} 

public void testMethodUnderTest_makeSpecificRealCalls() { 
    SomeAbstractClass myAbstractClass = 
     Mockito.mock(SomeAbstractClass.class, CALLS_REAL_METHODS); 
    SomeAbstractClass myObject = Mockito.mock(SomeObject.class); 
    // overrides the default answer 
    when(myAbstractClass.someMethod()).thenReturn(myObject); 

    myAbstractClass.methodUnderTest(); 

    verify(myAbstractClass).someMethod(); 
    verify(myObject).someOtherMethod(); 
} 

Forewarned हो कि SomeAbstractClass वास्तव में instantiated कभी नहीं है, तो आप अमूर्त वर्ग में किसी भी व्यवहार पर निर्भर करता है, तो परिवर्तक, वैरिएबल प्रारंभिकरण की तरह - इनलाइन प्रारंभिकरण सहित फ़ील्ड घोषित किए गए हैं - आपको उन कॉल को स्पष्ट रूप से स्वयं करने की आवश्यकता होगी।