有没有办法匹配以下示例例程的任何类参数?
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)
答案 0 :(得分:167)
另外两种方法(参见我对@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()
实际返回的内容: - )
答案 1 :(得分:44)
如果没有演员表,还有另一种方法可以做到:
when(a.method(Matchers.<Class<A>>any())).thenReturn(b);
此解决方案强制方法any()
返回Class<A>
类型,而不是其默认值(Object
)。
答案 2 :(得分:34)
如果您不知道需要导入哪个套餐:
import static org.mockito.Matchers.any;
any(SomeClass.class)
OR
import org.mockito.Matchers;
Matchers.any(SomeClass.class)
答案 3 :(得分:21)
怎么样:
when(a.method(isA(A.class))).thenReturn(b);
或:
when(a.method((A)notNull())).thenReturn(b);
答案 4 :(得分:7)
来自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);
答案 5 :(得分:0)
以上示例均不适合我,因为我需要针对不同的类类型参数多次模拟一个方法。
相反,这是有效的。
//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));
如您所见,我将自定义 ArgumentMatchers 与 argThat 一起使用,不确定是否有更短的方法也适用。