Mockito 匹配任何类参数

有没有办法匹配下面例程的任何类参数?

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

无论哪个类被传递到 method,我如何返回 new B()?以下尝试仅适用于匹配 A的特定情况。

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

编辑 : 一个解决方案是

(Class<?>) any(Class.class)
370918 次浏览

这个怎么样:

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

或:

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

还有两种方法可以做到这一点(见我对@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);

其中 ClassOrSubclassMatcherorg.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()实际返回的内容: -)

还有另一种方法可以做到这一点,而不需要石膏:

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

这个解决方案强制方法 any()返回 Class<A>类型,而不是它的默认值(Object)。

如果您不知道需要导入哪个软件包:

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

或者

import org.mockito.ArgumentMatchers;
ArgumentMatchers.any(SomeClass.class)

米尔豪斯的解决方案不再适用于最近的版本

这个解决方案可以与 java 8和嘲弄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);

上面的示例都不适合我,因为我需要为不同的类类型参数多次模拟一个方法。

相反,这种方法奏效了。

//Handle InstrumentType.class
Mockito.doReturn(new InstrumentTypeMapper() {
@Override
public InstrumentType map(String sourceType) throws Exception {
return InstrumentType.Unknown;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat(new ArgumentMatcher<Class<InstrumentType>>() {
@Override
public boolean matches(Class<InstrumentType> argument) {
return InstrumentType.class.isAssignableFrom(argument);
}
}));


//Handle InstrumentSubType.class
Mockito.doReturn(new InstrumentSubTypeMapper() {
@Override
public InstrumentSubType map(String sourceType) throws Exception {
return InstrumentSubType.istNone;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat(new ArgumentMatcher<Class<InstrumentSubType>>() {
@Override
public boolean matches(Class<InstrumentSubType> argument) {
return InstrumentSubType.class.isAssignableFrom(argument);
}
}));

简而言之:

Mockito.doReturn(new InstrumentTypeMapper() {
@Override
public InstrumentType map(String sourceType) throws Exception {
return InstrumentType.Unknown;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat((ArgumentMatcher<Class<InstrumentType>>) InstrumentType.class::isAssignableFrom));


Mockito.doReturn(new InstrumentSubTypeMapper() {
@Override
public InstrumentSubType map(String sourceType) throws Exception {
return InstrumentSubType.istNone;
}
}).when(mappingLoader).load(any(ServiceCode.class), argThat((ArgumentMatcher<Class<InstrumentSubType>>) InstrumentSubType.class::isAssignableFrom));

正如你所看到的,我正在使用自定义 辩论比赛那个一起,不确定是否有一个更短的方法也工作。