2010-09-01 18 views
6

में एक तर्क कैप्चर करें मैं एक निश्चित कक्षा का परीक्षण कर रहा हूं। यह कक्षा आंतरिक रूप से "GetMethod" ऑब्जेक्ट को तुरंत चालू कर रही है जो "HttpClient" ऑब्जेक्ट को पास की जाती है जिसे परीक्षण कक्षा में इंजेक्शन दिया जाता है।मॉकिटो

मैं "एचटीपी क्लाइंट" कक्षा का मज़ाक उड़ा रहा हूं, लेकिन मुझे "GetMethod" कक्षा के एक विधि के व्यवहार को भी संशोधित करने की आवश्यकता होगी। मैं ArgumentCaptor के साथ खेल रहा हूं लेकिन मुझे लगता है कि "कब" कॉल में तत्काल वस्तु को पकड़ने में सक्षम नहीं है।

उदाहरण:

HttpClient mockHttpClient = mock(HttpClient.class); 
ArgumentCaptor<GetMethod> getMethod = ArgumentCaptor.forClass(GetMethod.class); 
when(mockHttpClient.executeMethod(getMethod.capture())).thenReturn(HttpStatus.SC_OK); 
when(getMethod.getValue().getResponseBodyAsStream()).thenReturn(new FileInputStream(source)); 

प्रतिक्रिया:

org.mockito.exceptions.base.MockitoException: 
No argument value was captured! 
You might have forgotten to use argument.capture() in verify()... 
...or you used capture() in stubbing but stubbed method was not called. 
Be aware that it is recommended to use capture() only with verify() 

उत्तर

4

ठीक है, इस तरह मैंने इसे हल किया है। थोड़ी सी गड़बड़ी हुई लेकिन किसी अन्य तरीके से नहीं मिला।

परीक्षण वर्ग में:

private GetMethod getMethod; 

public void testMethod() { 
    when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new ExecuteMethodAnswer()); 
    //Execute your tested method here. 
    //Acces the getMethod here, assert stuff against it. 
} 

private void setResponseStream(HttpMethodBase httpMethod, InputStream inputStream) throws NoSuchFieldException, IllegalAccessException { 
    Field privateResponseStream = HttpMethodBase.class.getDeclaredField("responseStream"); 
    privateResponseStream.setAccessible(true); 
    privateResponseStream.set(httpMethod, inputStream); 
} 

private class ExecuteMethodAnswer implements Answer { 
    public Object answer(InvocationOnMock invocation) throws FileNotFoundException, 
                  NoSuchFieldException, IllegalAccessException { 
     getMethod = (GetMethod) invocation.getArguments()[0]; 
     setResponseStream(getMethod, new FileInputStream(source)); 
     return HttpStatus.SC_OK; 
    } 
} 
+0

जब आप मेरा जवाब संपादित कर रहे थे तो आपने इसे पोस्ट किया था। खैर, हम दोनों ने इसे उसी तरह हल किया :) – amorfis

+0

हां, मुझे उपलब्ध टूल के साथ ऐसा करने का कोई और तरीका नहीं मिल रहा है। गंदा हैक :) लेकिन यह काम करता है जब यह चट्टानों! –

12

आप getMethod पर when का उपयोग नहीं कर सकते क्योंकि getMethod एक नकली नहीं है। यह अभी भी आपकी कक्षा द्वारा बनाई गई असली वस्तु है।

ArgumentCaptor का एक अलग उद्देश्य है। section 15 here देखें।

आप अपना कोड अधिक टेस्टेबल बना सकते हैं। आम तौर पर, कक्षाएं जो अन्य वर्गों के नए उदाहरण बना रही हैं, परीक्षण करना मुश्किल है। कुछ कारखाने को प्राप्त/पोस्ट विधियों के निर्माण के लिए इस कारखाने में रखें, फिर इस फैक्ट्री का परीक्षण करें, और इसे मॉक/पोस्ट विधियां बनाएं।

public class YourClass { 
    MethodFactory mf; 

    public YourClass(MethodFactory mf) { 
    this.mf = mf; 
    } 

    public void handleHttpClient(HttpClient httpClient) { 
    httpClient.executeMethod(mf.createMethod()); 
    //your code here 
    } 
} 

फिर परीक्षा में आप कर सकते हैं:

HttpClient mockHttpClient = mock(HttpClient.class); 
when(mockHttpClient.executeMethod(any(GetMethod.class)).thenReturn(HttpStatus.SC_OK); 

MethodFactory factory = mock(MethodFactory.class); 
GetMethod get = mock(GetMethod.class); 
when(factory.createMethod()).thenReturn(get); 
when(get.getResponseBodyAsStream()).thenReturn(new FileInputStream(source)); 

अद्यतन

तुम भी कुछ बुरा हैक कोशिश कर सकते हैं, और Answer और GetMethod के निजी हिस्सों तक पहुँचने;) प्रतिबिंब द्वारा। (यह वास्तव में बुरा हैक है)

when(mockHttpClient.executeMethod(any(GetMethod.class))).thenAnswer(new Answer() { 
    Object answer(InvocationOnMock invocation) { 
    GetMethod getMethod = (GetMethod) invocation.getArguments()[0]; 

    Field respStream = HttpMethodBase.class.getDeclaredField("responseStream"); 
    respStream.setAccessible(true); 
    respStream.set(getMethod, new FileInputStream(source)); 

    return HttpStatus.SC_OK; 
    } 
}); 
+0

मैं जानता हूँ कि इन्स्टेन्शियशन कक्षाओं का परीक्षण करने के कठिन बना देता है, लेकिन इस मामले में एक कारखाने overkill होगा, और मैं बहुत अधिक कार्यान्वयन बदलने के लिए स्वतंत्र नहीं हूँ। –

संबंधित मुद्दे