Mockito соответствует любому аргументу класса - PullRequest
128 голосов
/ 21 сентября 2011

Есть ли способ сопоставить какой-либо аргумент класса из приведенной ниже примерной процедуры?

class A {
     public B method(Class<? extends A> a) {}
}

Как я могу всегда возвращать new B() независимо от того, какой класс передан в method? Следующая попытка работает только для конкретного случая, где A совпадает.

A a = new A();
B b = new B();
when(a.method(eq(A.class))).thenReturn(b);

РЕДАКТИРОВАТЬ : Одно решение

(Class<?>) any(Class.class)

Ответы [ 5 ]

168 голосов
/ 07 октября 2011

Еще два способа сделать это (см. Мой комментарий к предыдущему ответу @Tomasz Nurkiewicz):

Первый основан на том факте, что компилятор просто не позволит вам передать что-то неправильноеТип:

when(a.method(any(Class.class))).thenReturn(b);

Вы теряете точный набор текста (Class<? extends A>), но, вероятно, он работает так, как вам нужно.

Второй вариант намного сложнее, но, возможно, лучшерешение, если вы действительно хотите быть уверены, что аргумент method() является A или подклассом A:

when(a.method(Matchers.argThat(new ClassOrSubclassMatcher<A>(A.class)))).thenReturn(b);

Где ClassOrSubclassMatcher является org.hamcrest.BaseMatcher определяется как:

public class ClassOrSubclassMatcher<T> extends BaseMatcher<Class<T>> {

    private final Class<T> targetClass;

    public ClassOrSubclassMatcher(Class<T> targetClass) {
        this.targetClass = targetClass;
    }

    @SuppressWarnings("unchecked")
    public boolean matches(Object obj) {
        if (obj != null) {
            if (obj instanceof Class) {
                return targetClass.isAssignableFrom((Class<T>) obj);
            }
        }
        return false;
    }

    public void describeTo(Description desc) {
        desc.appendText("Matches a class or subclass");
    }       
}

Фу!Я бы выбрал первый вариант, пока вам действительно не потребуется более точный контроль над тем, что на самом деле возвращает method(): -)

45 голосов
/ 12 января 2016

Есть еще один способ сделать это без приведения:

when(a.method(Matchers.<Class<A>>any())).thenReturn(b);

Это решение заставляет метод any() возвращать тип Class<A>, а не его значение по умолчанию (Object).

35 голосов
/ 06 апреля 2016

Если вы не знаете, какой пакет вам нужно импортировать:

import static org.mockito.Matchers.any;
any(SomeClass.class)

ИЛИ

import org.mockito.Matchers;
Matchers.any(SomeClass.class)
22 голосов
/ 21 сентября 2011

Как насчет:

when(a.method(isA(A.class))).thenReturn(b);

или

when(a.method((A)notNull())).thenReturn(b);
7 голосов
/ 04 августа 2017

решение от millhouse больше не работает с последней версией mockito

Это решение работает с java 8 и mockito 2.2.9

, где ArgumentMatcher является экземпляром org.mockito.ArgumentMatcher

public class ClassOrSubclassMatcher<T> implements ArgumentMatcher<Class<T>> {

   private final Class<T> targetClass;

    public ClassOrSubclassMatcher(Class<T> targetClass) {
        this.targetClass = targetClass;
    }

    @Override
    public boolean matches(Class<T> obj) {
        if (obj != null) {
            if (obj instanceof Class) {
                return targetClass.isAssignableFrom( obj);
            }
        }
        return false;
    }
}

И использование

when(a.method(ArgumentMatchers.argThat(new ClassOrSubclassMatcher<>(A.class)))).thenReturn(b);
...