14

I am attempting to verify that a method with the following signature was called:

public void process(Map<String, Set<String>> data) {
  ...
}

The nested parameterized Set is causing me difficulties. I can get it to verify correctly with the any() matcher like so:

verify(dataProcessor).process(Matchers.<Map<String, Set<String>>> any());

As described in Mockito: Verifying with generic parameters although annoyingly it doesn't work if I do a direct static import of Matchers.any and call it as just:

verify(dataProcessor).process(<Map<String, Set<String>>> any())

But anyMapOf(clazz, clazz) seems the more appropriate matcher in this case. Since you can't do Set.class I'm not sure how you would do this. The following doesn't work because of the lack of generic:

verify(dataProcessor).process(anyMapOf(String.class, Set.class));

Is it possible to verify this situation with anyMapOf or should I stick with Matchers.<>any()?

Community
  • 1
  • 1
Ben Pennell
  • 449
  • 1
  • 3
  • 13
  • Your method signature already constrains what argument type the method uses, why don't you just use `any()`? Code not calling your method with a `Map>` will not even compile... – fge Feb 14 '14 at 15:32
  • @fge Java type inference doesn't infer type variables in the call to `any` based on the parameter types available in `process`, because `process` could have overloads and/or type parameters of its own. It does do so in return values and fields, because the type is already defined explicitly as the return value type or field type. It's all in [the extremely-opaque JLS 15.12.2](http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2). – Jeff Bowman Feb 14 '14 at 21:10

1 Answers1

27

There's no way to use anyMapOf to do this. It's designed to help with the simple case of mapping simple classes to simple classes in Java 7, and yours is more complex than that.

Java 8 parameter inference improved, so in Java 8, you can just use any().

verify(dataProcessor).process(Matchers.any());

Barring that, the best way to make this look is either like you wrote above:

verify(dataProcessor).process(Matchers.<Map<String, Set<String>>>any());

Or by extracting the matcher to a static function, which gives Java just enough information it needs to infer the type on its own:

@Test public void yourTest() {
  // ...
  verify(dataProcessor).process(anyStringSetMap());
}

private static Map<String, Set<String>> anyStringSetMap() {
  return any();
}

(Caveat: Note that the return value of anyStringSetMap() is null; it's the side-effect of calling any that you're looking for. The extracted method is just to inform the Java compiler of the expected return type; beware that doing anything fancier will probably break in really-quite-interesting ways.)

Dimitri Hautot
  • 438
  • 5
  • 12
Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Thanks Jeff, its good to get confirmation on this. If it becomes a common enough case in this project then perhaps I'll go the direction of new static matcher. – Ben Pennell Feb 15 '14 at 01:43