Mockito match any class argument

后端 未结 5 1889
忘了有多久
忘了有多久 2020-12-22 18:48

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

class A {
     public B method(Class a) {}
}

How

相关标签:
5条回答
  • 2020-12-22 19:32

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

    0 讨论(0)
  • 2020-12-22 19:36

    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);
    
    0 讨论(0)
  • 2020-12-22 19:37

    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)
    
    0 讨论(0)
  • 2020-12-22 19:44

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

    0 讨论(0)
  • 2020-12-22 19:46

    How about:

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

    or:

    when(a.method((A)notNull())).thenReturn(b);
    
    0 讨论(0)
提交回复
热议问题