177

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

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

无论传入哪个类,我如何始终返回 a ?以下尝试仅适用于匹配的特定情况。new B()methodA

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

编辑:一种解决方案是

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

6 回答 6

213

还有两种方法(请参阅我对@Tomasz Nurkiewicz 上一个答案的评论):

第一个依赖于编译器根本不会让您传入错误类型的事实:

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

您丢失了确切的输入(Class<? extends A>),但它可能会按照您的需要工作。

第二个涉及更多,但如果您真的想确定 to 的参数method()是 的一个A或一个子类,则可以说是一个更好的解决方案A

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

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

于 2011-10-07T03:59:19.760 回答
66

还有另一种不强制转换的方法:

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

此解决方案强制方法any()返回Class<A>类型而不是其默认值 ( Object)。

于 2016-01-12T20:07:43.677 回答
57

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

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

或者

import org.mockito.ArgumentMatchers;
ArgumentMatchers.any(SomeClass.class)
于 2016-04-06T03:09:11.853 回答
30

怎么样:

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

或者:

when(a.method((A)notNull())).thenReturn(b);
于 2011-09-21T13:15:05.137 回答
11

millhouse 的解决方案不再适用于最新版本的 mockito

该解决方案适用于 java 8 和 mockito 2.2.9

ArgumentMatcherinstanceof在哪里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);
于 2017-08-04T07:21:53.407 回答
1

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

相反,这有效。

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

如您所见,我将自定义ArgumentMatchersargThat一起使用,不确定是否有更短的方法也可以。

于 2021-08-03T13:26:37.653 回答