Mockito 匹配任何类参数

发布于 2024-12-05 17:51:18 字数 431 浏览 1 评论 0原文

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

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

无论将哪个类传递给方法,如何才能始终返回new B()?以下尝试仅适用于 A 匹配的特定情况。

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

编辑:一种解决方案是

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

Is there a way to match any class argument of the below sample routine?

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

How can I always return a new B() regardless of which class is passed into method? The following attempt only works for the specific case where A is matched.

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

EDIT: One solution is

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

泪是无色的血 2024-12-12 17:51:19

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

该解决方案适用于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);

the solution from millhouse is not working anymore with recent version of mockito

This solution work with java 8 and mockito 2.2.9

where ArgumentMatcher is an instanceof 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;
    }
}

And the use

when(a.method(ArgumentMatchers.argThat(new ClassOrSubclassMatcher<>(A.class)))).thenReturn(b);
冷清清 2024-12-12 17:51:19

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

相反,这是有效的。

//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一起使用,不确定是否有更短的方法这也有效。

None of the examples above worked for me, as I'm required to mock one method multiple times for different class type parameters.

Instead, this works.

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

This is the short version:

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

As you can see, I'm using custom ArgumentMatchers together with argThat, not sure if there is a shorter way that also works.

于我来说 2024-12-12 17:51:18

还有两种方法可以做到这一点(请参阅我对 @Tomasz Nurkiewicz 之前的答案的评论):

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

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

您丢失了确切的类型( Class),但它可能会按照您的需要工作。

第二个涉及更多,但如果您确实想要确保 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() 实际返回的内容:-)

Two more ways to do it (see my comment on the previous answer by @Tomasz Nurkiewicz):

The first relies on the fact that the compiler simply won't let you pass in something of the wrong type:

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

You lose the exact typing (the Class<? extends A>) but it probably works as you need it to.

The second is a lot more involved but is arguably a better solution if you really want to be sure that the argument to method() is an A or a subclass of A:

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

Where ClassOrSubclassMatcher is an org.hamcrest.BaseMatcher defined as:

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");
    }       
}

Phew! I'd go with the first option until you really need to get finer control over what method() actually returns :-)

永不分离 2024-12-12 17:51:18

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

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

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

There is another way to do that without cast:

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

This solution forces the method any() to return Class<A> type and not its default value (Object).

黑白记忆 2024-12-12 17:51:18

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

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

或者

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

If you have no idea which Package you need to import:

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

OR

import org.mockito.ArgumentMatchers;
ArgumentMatchers.any(SomeClass.class)
爱格式化 2024-12-12 17:51:18

怎么样:

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

或者:

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

How about:

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

or:

when(a.method((A)notNull())).thenReturn(b);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文