web-dev-qa-db-ja.com

Mockitoは任意のクラス引数に一致します

以下のサンプルルーチンのクラス引数に一致する方法はありますか?

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

どのようにしてmethodに渡されるクラスに関係なくalwaysnew B()を返すことができますか?次の試行は、Aが一致する特定の場合にのみ機能します。

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

EDIT:1つのソリューションは

(Class<?>) any(Class.class)
127
Johan Sjöberg

それを行うには、さらに2つの方法があります(@Tomasz Nurkiewiczによる以前の回答に関する私のコメントを参照)。

最初は、コンパイラが間違ったタイプのものを渡さないようにするという事実に依存しています。

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

正確なタイピング(Class<? extends A>)は失われますが、おそらく必要に応じて機能します。

2番目の方法はより複雑ですが、実際に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");
    }       
}

ふう! reallymethod()が実際に返すものをより細かく制御する必要があるまで、最初のオプションを使用します:-)

167
millhouse

キャストせずにそれを行う別の方法があります。

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

このソリューションは、メソッドany()がデフォルト値(Object)ではなくClass<A>タイプを返すように強制します。

45
anmaia

インポートする必要のあるパッケージがわからない場合:

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

OR

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

どうですか:

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

または:

when(a.method((A)notNull())).thenReturn(b);
21

ミルハウスのソリューションは、モッキートの最新バージョンではもう機能していません

このソリューションは、Java 8およびmockito 2.2.9で動作します

ArgumentMatcherorg.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);
7
Bertrand Cedric