250

is it possible to pass the type of an interface with generics?

The interface:

public interface AsyncCallback<T>

In my test method:

Mockito.any(AsyncCallback.class)

Putting <ResponseX> behind or for .class didnt work.

bric3
  • 40,072
  • 9
  • 91
  • 111
lrxw
  • 3,576
  • 7
  • 32
  • 46

8 Answers8

444

There is a type-safe way: use ArgumentMatchers.any() and qualify it with the type:

ArgumentMatchers.<AsyncCallback<ResponseX>>any()
Jouramie
  • 179
  • 5
  • 16
thSoft
  • 21,755
  • 5
  • 88
  • 103
  • 6
    I confirm this answer works and correctly suppresses the warning. – kevinarpe Mar 17 '14 at 12:51
  • 1
    This isn't really safer since the actual method can only be called with the correctly typed argument anyway. It was just necessary to satisfy the pre-java8 compiler which lacked this kind of type inference. – herman Dec 17 '14 at 11:36
  • I used something like this ResponseEntity>> responseEntity = Matchers.>>> any(); And it always returns null – Arun Aug 19 '16 at 14:04
  • 8
    With new versions of Mockito: `(Matchers.>any()` – pierrefevrier Aug 04 '17 at 13:19
  • 21
    `Matchers` is actually deprecated, but `ArgumentMatchers` did work. – guijob Dec 14 '17 at 21:56
  • The first one using ArgumentMatchers worked for me and the second one using Matchers is deprecated. I had some confusion on what is ResponseX. however got the answer myself, in my case i wrote like this : ArgumentMatchers.>any() – Barani r Jul 30 '18 at 11:51
  • How to write it in Kotlin? – Malachiasz May 16 '19 at 09:16
  • 7
    `ArgumentMatchers.>any()` - IDE hints me that Explicit type arguments can be inferred. It means that there is no requirement to explicitly define types and `ArgumentMatchers.any()` will have the same result – Alex Sep 09 '19 at 09:11
  • 1
    This also works using just `Mockito.>any()`. – gagarwa Sep 05 '20 at 02:58
  • 3
    But hold on! `any()` and `any(Class)` do not do the same thing. The no-arg matches anything, but the 1-arg only matches things of that class. So how can do you this where, like the original poster, you need to use `any(Class)` and not `any()`? – QuantumMechanic Jul 28 '21 at 21:36
  • 2
    @QuantumMechanic -- yup, same question here. Not possible with silly Java generics? – Josh M. Feb 22 '23 at 02:26
81

Using Java 8, you can simply use any() (assuming static import) without argument or type parameter because of enhanced type inference. The compiler now knows from the target type (the type of the method argument) that you actually mean Matchers.<AsyncCallback<ResponseX>>any(), which is the pre-Java 8 solution.

herman
  • 11,740
  • 5
  • 47
  • 58
  • 1
    Wouldn't `any()` match `AsyncCallback` as well? – Matthew Read Oct 03 '16 at 15:32
  • @MatthewRead Using `AsyncCallback` should not even compile if the argument type is 'AsyncCallback'. – herman Oct 03 '16 at 17:29
  • 1
    I'm wondering about a situation where the argument type is generic as well, but you only want to mock it for one concrete type (or mock it for multiple types in different ways). Given `when(x.y(any())).thenAnswer(...)` for example, where `y` is `public T y(AsyncCallback arg)`. Perhaps it would be better to check the type in the answer, if that is what's needed? – Matthew Read Oct 03 '16 at 18:04
  • 2
    @MatthewRead Due to erasure, the actual type cannot be checked at runtime by Mockito. So you can't even use `isA()`. If the object holds a `Class` object corresponding to the type, and the interface exposes this, I guess you could check it in a custom matcher. Or for example in case of a `Collection` you could check the type of the elements. – herman Oct 03 '16 at 22:05
  • Ah, you're completely right. I was actually just reading more on type erasure and for some reason didn't connect it to this. Thanks for explaining! – Matthew Read Oct 03 '16 at 22:34
  • 1
    `Matchers` was replaced by `ArgumentMatchers` in Mockito v2 – bheussler Jun 24 '17 at 03:44
  • This is only true when there is not a conflicting method overload, and you need to tell the compiler which one to call. e.g. `myMethod(Type1)` & `myMethod(Type2)` you can't just do `myMethod(any())`. – M. Justin Oct 20 '20 at 17:07
  • Is it some JAVA8 feature allowing to avoid type checks? Could you please let me know where I can read about it? – Alex Nov 18 '20 at 09:32
  • 1
    @YuraHoy No runtime type check is being done here even before version 8. The type had to be added just to satisfy the compiler. Now the compiler infers the type from the method signature. See https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html – herman Nov 19 '20 at 10:32
23

I had to adopt the following mechamism to allow for generics:

import static org.mockito.Matchers.any;
List<String> list = any();
when(callMyMethod.getResult(list)).thenReturn(myResultString);

Hope this helps someone.

theINtoy
  • 3,388
  • 2
  • 37
  • 60
5

Posting pierrefevrier comment as answer which might be useful if it present in a answer instead of comments.

With new versions of Mockito: (Matchers.<AsyncCallback<ResponseX>>any()

sag
  • 5,333
  • 8
  • 54
  • 91
4

Further to thSoft's answer putting the qualified call to any() in method meant I could remove the qualification since the return type allowed inference:

private HashMap<String, String> anyStringStringHashMap() {
    return Matchers.any();
}
JWGS
  • 183
  • 1
  • 3
3

I had a similar problem using Spring Example:

Mockito.when(repo.findAll(Mockito.<Example<SrvReqToSupplierComment>>any()))
            .thenReturn(Lists.emptyList());

Here, you have to use qualification, b/c findAll method can take multiple types, like Sort and Iterable. You can also use Mockito.any(Example.class) of course with the type safety warning.

gagarwa
  • 1,426
  • 1
  • 15
  • 28
  • It was my problem too. I use generally a static import for org.mockito.Mockito.*, but in this case only the when() method could be used without qualification, the any() method needs the qualification. – Géza Jan 13 '21 at 11:07
1

Using a qualified generics type with the no-argument any() method works (i.e. ArgumentMatchers.<AsyncCallback<ResponseX>>any()), but can get unwieldy for longer generics expressions. An alternative is to put a no-argument any() call in its own generic method, using the specific generic type as the return type:

private static <T> AsyncCallback<T> anyAsyncCallback() {
  return ArgumentMatchers.any()
}

Usage

Mockito.verify(mockObject).performCallback(any(), anyAsyncCallback())
M. Justin
  • 14,487
  • 7
  • 91
  • 130
0

You can just cast it, adding suppress warnings if you like:

@SuppressWarnings("unchecked")    
AsyncCallback<ResponseX> callback = Mockito.any(AsyncCallback.class)

If Java allowed 'generic' generics they could have a method like this which is what you are looking for

private static <T, E> T<E> mock(Class<T<E>> clazz)
Garrett Hall
  • 29,524
  • 10
  • 61
  • 76
  • When I tried this, I received an error in my test: `You cannot use argument matchers outside of verification or stubbing.` – kevinarpe Mar 17 '14 at 12:50
  • Not a good idea to use `@SuppressWarnings`: pre-java 8, if you were going to assign it to a separate variable, you could just use `any()` as in theINtoy's answer. Now with java 8, `any()` can be used inline without the need for a separate assignment. – herman Dec 17 '14 at 11:43
  • @kevinarpe if you have multiple argument matchers they must be called in order as the Java language specifies. – TWiStErRob Mar 16 '16 at 13:17