मॉकिटो: बाउंडेड वाइल्ड-कार्ड्स के साथ रिटर्न टाइप करने वाले स्टबिंग तरीके


135

इस कोड पर विचार करें:

public class DummyClass {
    public List<? extends Number> dummyMethod() {
        return new ArrayList<Integer>();
    }
}
public class DummyClassTest {
    public void testMockitoWithGenerics() {
        DummyClass dummyClass = Mockito.mock(DummyClass.class);
        List<? extends Number> someList = new ArrayList<Integer>();
        Mockito.when(dummyClass.dummyMethod()).thenReturn(someList); //Compiler complains about this
    }
}

संकलक उस रेखा के बारे में शिकायत करता है जो उस व्यवहार को ठूंठ करने की कोशिश कर रहा है dummyMethod()। कोई भी इस बात पर ध्यान केंद्रित करता है कि कोई स्टबिंग विधियों के बारे में कैसे जाता है जो कि बंधे हुए वाइल्ड-कार्ड्स के साथ एक प्रकार का है?


क्या आप सामान्य प्रकार दिखाने के लिए अपने कोड स्निपेट को अपडेट कर सकते हैं?
मिलहाउस

1
किया हुआ। मुझे पहले और कोड टैग हटाने थे, वे छीन रहे थे <? संख्या> प्रकार की घोषणा से फैली हुई है।
शिखर मिश्रा

जवाबों:


190

तुम भी गैर प्रकार सुरक्षित विधि का उपयोग कर सकते हैं doReturn , इस उद्देश्य के लिए

@Test
public void testMockitoWithGenerics()
{
    DummyClass dummyClass = Mockito.mock(DummyClass.class);
    List<? extends Number> someList = new ArrayList<Integer>();

    Mockito.doReturn(someList).when(dummyClass).dummyMethod();

    Assert.assertEquals(someList, dummyClass.dummyMethod());
}

जैसा कि मॉकिटो के Google समूह पर चर्चा की गई है

हालांकि यह तुलना में सरल है thenAnswer, फिर से ध्यान दें कि यह सुरक्षित नहीं है। यदि आप प्रकार की सुरक्षा के बारे में चिंतित हैं, तो मिलहाउस का उत्तर सही है।

अतिरिक्त जानकारिया

स्पष्ट होने के लिए, यहाँ देखे गए संकलक त्रुटि है,

The method thenReturn(List<capture#1-of ? extends Number>) in the type OngoingStubbing<List<capture#1-of ? extends Number>> is not applicable for the arguments (List<capture#2-of ? extends Number>)

मेरा मानना ​​है कि कंपाइलर ने whenकॉल के दौरान पहले वाइल्डकार्ड प्रकार को असाइन किया है और फिर पुष्टि नहीं कर सकता है कि thenReturnकॉल में दूसरा वाइल्डकार्ड प्रकार समान है।

ऐसा लगता है कि यह thenAnswerइस समस्या में नहीं चलता है क्योंकि यह एक वाइल्डकार्ड प्रकार को स्वीकार करता है जबकि thenReturnगैर-वाइल्डकार्ड प्रकार लेता है, जिसे कैप्चर किया जाना चाहिए। मॉकिटो के ऑनगोइंगस्टबिंग से ,

OngoingStubbing<T> thenAnswer(Answer<?> answer);
OngoingStubbing<T> thenReturn(T value);

यह आंशिक रूप से मेरी भी मदद करता है ... लेकिन क्या होगा यदि आप जिस सूची से लौटने की उम्मीद करते हैं वह खाली नहीं है?
ttati

खाली सूची होने के बजाय आप यह भी कर सकते हैं: सूची <संख्या> someList = नया एरियरिस्ट <Integer> (); someList.add (anumber);
15

32

मुझे लगता है कि आप someListकुछ ज्ञात मूल्यों के साथ लोड करने में सक्षम होना चाहते हैं; यहाँ एक दृष्टिकोण है जो Answer<T>सब कुछ सुरक्षित रखने के लिए एक टेम्पर्ड हेल्पर विधि का उपयोग करता है :

@Test
public void testMockitoWithGenericsUsingAnswer()
{
    DummyClass dummyClass =  Mockito.mock(DummyClass.class);

    Answer<List<Integer>> answer = setupDummyListAnswer(77, 88, 99);
    Mockito.when(dummyClass.dummyMethod()).thenAnswer(answer);

    ...
}

private <N extends Number> Answer<List<N>> setupDummyListAnswer(N... values) {
    final List<N> someList = new ArrayList<N>();

    someList.addAll(Arrays.asList(values));

    Answer<List<N>> answer = new Answer<List<N>>() {
        public List<N> answer(InvocationOnMock invocation) throws Throwable {
            return someList;
        }   
    };
    return answer;
}

17

मैंने कल वही बात मारी। @ Nondescript1 और @millhouse दोनों के जवाबों ने मुझे वर्कअराउंड का पता लगाने में मदद की। मैंने बहुत अधिक @millhouse के समान कोड का उपयोग किया है, सिवाय इसके कि मैंने इसे थोड़ा अधिक सामान्य बना दिया, क्योंकि मेरी त्रुटि एक के कारण नहीं थी java.util.List, लेकिन थी com.google.common.base.Optional। मेरी छोटी सहायक विधि इसलिए किसी भी प्रकार की अनुमति देती है Tऔर न कि सिर्फ List<T>:

public static <T> Answer<T> createAnswer(final T value) {
    Answer<T> dummy = new Answer<T>() {
        @Override
        public T answer(InvocationOnMock invocation) throws Throwable {
            return value;
        }
    };
    return dummy;
}

इस सहायक विधि से आप लिख सकते हैं:

Mockito.when(dummyClass.dummyMethod()).thenAnswer(createAnswer(someList));

यह बस ठीक संकलन करता है और thenReturn(...)विधि के समान काम करता है ।

किसी को पता है कि क्या त्रुटि है कि जावा संकलक का उत्सर्जन एक कंपाइलर बग है या यदि कोड वास्तव में गलत है?


यह सीधा, सरल और लगता है, जैसा कि मैं बता सकता हूं, सही है। मुझे यकीन नहीं है कि मॉकिटो ऐसा कुछ क्यों नहीं प्रदान करता है ....... जब तक यह नहीं करता है?
वाकाओ

14
जावा 8 में इसे छोटा किया जा सकता है: Mockito.when(dummyClass.dummyMethod()).thenAnswer(x -> someList)इसलिए उपयोगिता विधि की कोई आवश्यकता नहीं है
फिकोवनिक

1
@fikovnik क्या एक महान खोज "तत्पश्चात"!
बोरबज़

5

मैं fikovnik की टिप्पणी को यहां एक उत्तर में बदल रहा हूं ताकि इसे अधिक दृश्यता मिल सके क्योंकि मुझे लगता है कि यह जावा 8+ का उपयोग करके सबसे सुरुचिपूर्ण समाधान है।

Mockito प्रलेखन उपयोग करने की सलाह doReturn()एक अंतिम उपाय के रूप में (के रूप में स्वीकार किए जाते हैं जवाब में सुझाव दिया)।

इसके बजाय, प्रश्न में वर्णित कंपाइलर त्रुटि को प्रसारित करने के लिए, अनुशंसित मॉकिटो when()दृष्टिकोण का उपयोग लैम्बडा thenAnswer()(सहायक विधि के बजाय) के साथ किया जा सकता है :

Mockito.when(mockedClass.mockedMethod()).thenAnswer(x -> resultList)

यद्यपि यह किसी भी संकलन समय त्रुटियों को नहीं देता है, फिर भी जब हम प्रविष्टियों के साथ एक सूची पारित कर रहे हैं तो भी लौटी हुई सूची खाली है।
वेंकटेश कोल्ला - user2742897

0

यद्यपि मारेक रैडॉन्स्की द्वारा प्रस्तावित उपयोगिता पद्धति, एक अन्य विकल्प भी है, जिसे (IMHO अजीब लग रही) लैंबडा अभिव्यक्ति fikovnik ने सुझाव भी नहीं दिया है:

के रूप में इस सवाल का जवाब एक समान प्रश्न शो के लिए, आप भी निम्न का उपयोग कर सकते हैं:

BDDMockito.willReturn(someList).given(dummyClass).dummyMethod();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.