4

I am trying to mock some resources that are generated dynamically. In order to generate these resources, we must pass in a class argument. So for example:

FirstResourceClass firstResource = ResourceFactory.create(FirstResourceClass.class);

SecondResourceClass secondResource = ResourceFactory.create(SecondResource.class);

This is well and good until I tried to mock. I am doing something like this:

PowerMockito.mockStatic(ResourceFactory.class);
FirstResourceClass mockFirstResource = Mockito.mock(FirstResourceClass.class);
SecondResourceClass mockSecondResource = Mockito.mock(SecondResourceClass.class);

PowerMockito.when(ResourceFactory.create(Matchers.<Class<FirstResourceClass>>any()).thenReturn(mockFirstResource);
PowerMockito.when(ResourceFactory.create(Matchers.<Class<SecondResourceClass>>any()).thenReturn(mockSecondResource);

It seems like the mock is being injected into the calling class, but FirstResourceClass is being send mockSecondResource, which throws a compile error.

The issue is (I think) with the use of any() (which I got from this question). I believe I have to use isA(), but I'm not sure how to make that method call, as it requires a Class argument. I have tried FirstResourceClass.class, and that gives a compile error.

Community
  • 1
  • 1
Ajayc
  • 823
  • 2
  • 10
  • 16
  • `any()` matches anything, in any case, so this would not work. I would try `eq()` here: `Matchers.eq( FirstResourceClass.class )`. This way, your matcher matches when the argument is equal to the given class, which is probably what you want. – Florian Schaetz May 17 '17 at 06:06

1 Answers1

10

You want eq, as in:

PowerMockito.when(ResourceFactory.create(Matchers.eq(FirstResourceClass.class)))
    .thenReturn(mockFirstResource);

any() ignores the argument, and isA will check that your argument is of a certain class—but not that it equals a class, just that it is an instanceof a certain class. (any(Class) has any() semantics in Mockito 1.x and isA semantics in 2.x.)

isA(Class.class) is less specific than you need to differentiate your calls, so eq it is. Class objects have well-defined equality, anyway, so this is easy and natural for your use-case.

Because eq is the default if you don't use matchers, this also works:

PowerMockito.when(ResourceFactory.create(FirstResourceClass.class))
    .thenReturn(mockFirstResource);

Note that newer versions of Mockito have deprecated the Matchers name in favor of ArgumentMatchers, and Mockito.eq also works (albeit clumsily, because they're "inherited" static methods).

Jeff Bowman
  • 90,959
  • 16
  • 217
  • 251
  • Thanks! Matchers.eq() is what I was looking for. – Ajayc May 18 '17 at 21:30
  • Note that `Matchers` has been deprecated and replaced by `ArgumentMatchers`. – Abhijit Sarkar Sep 21 '20 at 21:47
  • @AbhijitSarkar That's in the final paragraph. – Jeff Bowman Sep 21 '20 at 21:49
  • @AbhijitSarkar Please don't pre-emptively edit, particularly incorrectly: You wrote "Edit" as a heading prefix to text that was included in version 1. I appreciate that you missed it but that doesn't mean that the text is incorrect or that it warrants an edit. – Jeff Bowman Sep 21 '20 at 21:59
  • @JeffBowman SO answers are community property, just like Wikipedia articles. Your time is appreciated, but you don't need to police your answers for years to come. They can, and should be, maintained as others feel best. – Abhijit Sarkar Sep 21 '20 at 22:02
  • @AbhijitSarkar I am comfortable with community edits that are correct and improve the post: I have suggested many and accepted many. Your edit changed my text, incorrectly (it is not an edit), [against style](https://meta.stackoverflow.com/a/255685/1426891), in ways that as an author (["_always_ respect the original author"](https://meta.stackoverflow.com/a/288836/1426891)) I do not believe to have clarified or improved the post. If you have additional concerns about how edits work on SO, I recommend asking on Meta. – Jeff Bowman Sep 21 '20 at 22:23