سؤال

كنت أحاول الحصول على السخرية من طريقة مع معلمات Vararg باستخدام Mockito:

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));

هذا يعمل ، على الرغم من أنني قد حذفت تمامًا وسيطة Varargs عند استخلاص الطريقة.

أي أدلة؟

هل كانت مفيدة؟

المحلول

Mockito 1.8.1 قدم anyvararg () matcher:

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);

نصائح أخرى

ميزة غير موثقة إلى حد ما: إذا كنت ترغب في تطوير مطابقة مخصصة يطابق وسائط Vararg التي تحتاجها لتنفيذها org.mockito.internal.matchers.VarargMatcher لكي تعمل بشكل صحيح. إنها واجهة علامة فارغة ، والتي بدونها لن تقارن Mockito الوسيطات بشكل صحيح عند استدعاء طريقة مع Varargs باستخدام Matcher الخاص بك.

علي سبيل المثال:

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);

بناء إجابة إيلي ليفين هنا هو حل أكثر عامة:

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);
    }

}

ثم يمكنك استخدامه مع متطابقات صفيف Hamcrest وهكذا:

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

(من الواضح أن الواردات الثابتة ستجعل هذا أكثر قابلية للقراءة.)

لقد كنت أستخدم الكود في إجابة بيتر ويستموكوت ولكن مع Mockito 2.2.15 يمكنك الآن القيام بما يلي:

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

أين arg1, arg2, arg3 هي varargs.

بناء على إجابة TopChef ،

لـ 2.0.31-beta ، اضطررت إلى استخدام mockito.anyvararg بدلاً من matchers.anyvararrg:

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

في حالتي ، فإن توقيع الطريقة التي أريد التقاط حجتها هي:

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

في هذه الحالة يجب أن تلقي بها صفيف البايت صراحة:

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

أنا أستخدم إصدار Mockito 1.10.19

يمكنك أيضًا حلقة الحجج:

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

على سبيل المثال ، تحقق من أنواعها ويلقي بها بشكل مناسب ، أضف إلى قائمة أو أي شيء آخر.

تكييف الإجابة من topchef ،

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

وفقًا لمستندات Java لـ Mockito 2.23.4 و Mockito.any () "يطابق أي شيء ، بما في ذلك Nulls و Varargs."

يمكنك تحقيق ذلك عن طريق تمرير التقاط argumentCaptor ثم استرداد Varargs كقائمة باستخدام "GetAllValues" ، راجع: https://stackoverflow.com/a/55621731/11342928

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top