मॉकिटो में varargs का ठीक से मिलान कैसे करें


152

मैं मॉकिटो का उपयोग करके वैरग मापदंडों के साथ एक विधि का उपयोग करने की कोशिश कर रहा हूं:

interface A {
  B b(int x, int y, C... c);
}

A a = mock(A.class);
B b = mock(B.class);

when(a.b(anyInt(), anyInt(), any(C[].class))).thenReturn(b);
assertEquals(b, a.b(1, 2));

यह काम नहीं करता है, हालांकि अगर मैं इसके बजाय ऐसा करता हूं:

when(a.b(anyInt(), anyInt())).thenReturn(b);
assertEquals(b, a.b(1, 2));

यह काम करता है, इसके बावजूद कि मैंने विधि को ठोकर मारते समय पूरी तरह से वार्गस तर्क को छोड़ दिया है।

कोई सुराग?


तथ्य यह है कि अंतिम उदाहरण काम करता है बल्कि तुच्छ है क्योंकि यह मामले से मेल खाता है जब शून्य वैरगेट पैरामीटर पारित हुए।
टॉपचेफ

जवाबों:


235

मॉकिटो 1.8.1 ने किसी भी वैरग () मैचर को पेश किया :

when(a.b(anyInt(), anyInt(), Matchers.<String>anyVararg())).thenReturn(b);

इसके लिए इतिहास भी देखें: https://code.google.com/archive/p/mockito/issues/62

पदावनत के बाद नया वाक्यविन्यास संपादित करें :

when(a.b(anyInt(), anyInt(), ArgumentMatchers.<String>any())).thenReturn(b);

26
anyVararg()इसके रिटर्न प्रकार के रूप में ऑब्जेक्ट है। किसी भी var arg type (जैसे String ..., Integer ..., आदि) के साथ संगत बनाने के लिए, एक स्पष्ट कास्टिंग करें। उदाहरण के लिए, यदि आपके पास है तो doSomething(Integer number, String ... args)आप मॉक / स्टब कोड को कुछ इस तरह से कर सकते हैं when(mock).doSomething(eq(1), (String) anyVarargs())। संकलन त्रुटि का ध्यान रखना चाहिए।
साइको पंच

15
जानकारी के लिए anyVararg अब पदावनत कर दिया गया है: "@deprecated के रूप में 2.1.0 किसी का उपयोग करें ()"
alexbt

5
Matchersअब org.hamcrest.Matchersवर्ग के साथ एक नाम के टकराव से बचने के लिए पदावनत कर दिया गया है और संभवतः मॉकिटो v3.0 में हटा दिया जाएगा। ArgumentMatchersइसके बजाय उपयोग करें ।
जोंड

31

कुछ हद तक अनिर्दिष्ट सुविधा: यदि आप एक कस्टम मिलानकर्ता विकसित करना चाहते हैं जो वार्ग तर्कों से मेल खाता है तो आपको इसे org.mockito.internal.matchers.VarargMatcherसही ढंग से काम करने के लिए इसे लागू करने की आवश्यकता है। यह एक खाली मार्कर इंटरफ़ेस है, जिसके बिना मॉकिटो आपके मिलानकर्ता का उपयोग करते हुए varargs के साथ एक विधि को लागू करते समय सही ढंग से तर्कों की तुलना नहीं करेगा।

उदाहरण के लिए:

class MyVarargMatcher extends ArgumentMatcher<C[]> implements VarargMatcher {
    @Override public boolean matches(Object varargArgument) {
        return /* does it match? */ true;
    }
}

when(a.b(anyInt(), anyInt(), argThat(new MyVarargMatcher()))).thenReturn(b);

7

एली लेविन के उत्तर पर निर्माण यहां एक अधिक सामान्य समाधान है:

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.mockito.ArgumentMatcher;
import org.mockito.internal.matchers.VarargMatcher;

import static org.mockito.Matchers.argThat;

public class VarArgMatcher<T> extends ArgumentMatcher<T[]> implements VarargMatcher {

    public static <T> T[] varArgThat(Matcher<T[]> hamcrestMatcher) {
        argThat(new VarArgMatcher(hamcrestMatcher));
        return null;
    }

    private final Matcher<T[]> hamcrestMatcher;

    private VarArgMatcher(Matcher<T[]> hamcrestMatcher) {
        this.hamcrestMatcher = hamcrestMatcher;
    }

    @Override
    public boolean matches(Object o) {
        return hamcrestMatcher.matches(o);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("has varargs: ").appendDescriptionOf(hamcrestMatcher);
    }

}

फिर आप हैमरेस्ट के ऐरे मैचर्स के साथ इसका इस्तेमाल कर सकते हैं:

verify(a).b(VarArgMatcher.varArgThat(
            org.hamcrest.collection.IsArrayContaining.hasItemInArray("Test")));

(स्पष्ट रूप से स्थैतिक आयात इस अधिक पठनीय को प्रस्तुत करेगा।)


अच्छा लगा। इसे मॉकिटो आईएमओ में बनाया जाना चाहिए।
ब्रीपेंट

मैंने Hamcrest के खिलाफ कुछ इस तरह से जोड़ने के लिए एक मुद्दा दायर किया। देखें github.com/mockito/mockito/issues/356
मार्क

क्या यह मॉकिटो 1 के लिए है? 2.10 के खिलाफ संकलन करने का प्रयास करने पर मुझे विभिन्न संकलन त्रुटियां मिलती हैं।
Frans

@ ऐसा लगता है कि 2 रिलीज अभी भी बीटा में था जब मैंने यह जवाब लिखा था, तो हाँ यह शायद मॉकिटो v1.10.19 या उसके लिए लिखा गया था। ( github.com/mockito/mockito/releases ) यह शायद अद्यतन करने योग्य है ...:
पीटर वेस्टमैकोट

3

मैं मॉकिटो 2.2.15 के साथ पीटर वेस्टमाकॉट के उत्तर में कोड का उपयोग कर रहा हूं लेकिन अब आप निम्नलिखित कार्य कर सकते हैं:

verify(a).method(100L, arg1, arg2, arg3)

जहाँ arg1, arg2, arg3varargs हैं


1

टॉपचेफ के जवाब पर बिल्डिंग,

2.0.31-बीटा के लिए मुझे माचिस के बजाय Mockito.anyVararg का उपयोग करना पड़ा।

when(a.b(anyInt(), anyInt(), Mockito.<String>anyVararg())).thenReturn(b);

3
जानकारी के लिए anyVararg अब पदावनत कर दिया गया है: "@deprecated के रूप में 2.1.0 किसी का उपयोग करें ()"
alexbt

0

मेरे मामले में उस पद्धति के हस्ताक्षर जो मैं उसके तर्क को पकड़ना चाहता हूं:

    public byte[] write(byte ... data) throws IOException;

इस मामले में आपको स्पष्ट रूप से बाइट सरणी में डालना चाहिए :

       when(spi.write((byte[])anyVararg())).thenReturn(someValue);

मैं नकली संस्करण का उपयोग कर रहा हूं 1.10.19


0

आप तर्कों पर भी प्रभाव डाल सकते हैं:

Object[] args = invocation.getArguments(); 
for( int argNo = 0; argNo < args.length; ++argNo) { 
    // ... do something with args[argNo] 
}

उदाहरण के लिए, उनके प्रकारों की जाँच करें और उन्हें उचित रूप से डालें, सूची में या जो भी जोड़ें।


0

@Topchef से उत्तर को अपनाना,

Mockito.when(a.b(Mockito.anyInt(), Mockito.anyInt(), Mockito.any())).thenReturn(b);

मॉकिटो 2.23.4 के लिए जावा डॉक्स के अनुसार, मॉकिटो.यानी () "कुछ भी मेल खाता है, जिसमें नल और वर्गर भी शामिल हैं।"


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