Mockito.any returns null - java

I am trying to mock a static method with parameters like this :
Mockito.when(StaticClass.staticMethod(Mockito.any(A.class),
Mockito.any(B.class), SomeEnum.FOO))
.thenReturn(true);
I have added the following annotations :
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Parameterized.class)
#PrepareForTest({StaticClass.class, A.class, B.class})
But Mockito.any always returns null. Why ?

Short answer: Use doReturn().when() instead of when().then()
Long answer can be found over here:
How do Mockito matchers work?
Matchers return dummy values such as zero, empty collections, or null.
Mockito tries to return a safe, appropriate dummy value, like 0 for
anyInt() or any(Integer.class) or an empty List for
anyListOf(String.class). Because of type erasure, though, Mockito
lacks type information to return any value but null for any()
NullPointerException or other exceptions: Calls to
when(foo.bar(any())).thenReturn(baz) will actually call foo.bar(null),
which you might have stubbed to throw an exception when receiving a
null argument. Switching to doReturn(baz).when(foo).bar(any()) skips
the stubbed behavior.
Side Note: This issue could also be described something like, How to use Mockito matchers on methods that have precondition checks for null parameters?

Firstly, you can't mix matchers with actual arguments. You should use a matcher for the SomeEnum argument too:
Mockito.when(StaticClass.staticMethod(Mockito.any(A.class),
Mockito.any(B.class), Mockito.eq(SomeEnum.FOO))
.thenReturn(true);
Secondly, the any() methods should return null. That is exactly what they do. If you look at the code for these methods they return the default value for the class type if it is primitive wrapper object (like Integer, Boolean etc.) otherwise it returns null:
public <T> T returnFor(Class<T> clazz) {
return Primitives.isPrimitiveOrWrapper(clazz) ? Primitives.defaultValueForPrimitiveOrWrapper(clazz) : null;
}

You are getting things wrong. The one and only purpose of matcher methods such as any() is to match the arguments that come in at execution time.
You use these methods to instruct the mocking framework what calls you expect to happen. Or the other way round you use them to say: if this or that is coming in as argument then do this or that.
Therefore you absolutely do not care about the results of matcher invocations.
In that sense your question is indicating that your usage of the mocking framework is going the wrong way. Thus the only answer we can give regarding your current input: A) do some more research how to use mocking and B) then rework your question to be clear about your problem.

It was because it was a Parameterized test, and I did the mockStatic in the #Before method. When I do the mockStatic in the same method, it works.

Related

Mock - make a spy class method return a specific value

I'm running some unit tests on a methodA of a spied instance of a class (let's say instance is myClass), which uses a helper method (lets call it helper(long num, ObjectA obA, ObjectB obB)) to determine the boolean value of a flag
The parameters of this class are all mocked, the class is instantiated with a spy call, and the method itself is a protected method with 3 parameters. The method is called with every run of methodA. MethodA sets the values of the parameters for the helper method
My question is, is there a way to make, in this specific test, the helper method return true?
I've tried to, using the following:
when(myClass.shouldSetFlag(anyLong(), any(ObjectA.class), any(ObjectB.class))).thenReturn(true);
but every time I get a null pointer exception.
Would really appreciate some insight, thanks!
Since you've provided only one line of code and no stack trace, I assume the NullPointerException is thrown from the shouldSetFlag method.
When you mock the method using when(...) Mockito actually replaces the matchers with default values during the method call in this line (it's still Java code, the method is still called). If you act on ObjectA or ObjectB instances inside the method, the actual code encounters a null reference and the exception is thrown.
From the docs:
Matcher methods like anyObject(), eq() do not return matchers. Internally, they record a matcher on a stack and return a dummy value (usually null).
You can also observe that in the Mockito code, since it's open source.
To work around that use doReturn(...) (see the docs here) - the actual method will not be called while mocking, yet it still will be registered in Mockito.

mockito when with third party class

I need to use a third party class in Mockito.when as parameter. The class does not have equals implementation and hence Mockito.when always returns null except the case where any() is used.
The below always returns null:
when(obj.process(new ThirdParytClass())).thenReturn(someObj);
however, this works
when(obj.process(any(ThirdParytClass.class))).thenReturn(someObj);
But, the problem is the process() method is called twice in the actual code and the use of any() is ambiguous and does not help in covering the multiple scenarios to test.
Extending the class does not help and also leads to other complications.
Is there a way to address the issue.
If a class doesn't implement a (sensible) equals(Object), you can always match instances yourself by implementing your own ArgumentMatcher. Java 8's functional interfaces make this pretty easy to write (not that it was such a big hardship in earlier versions, but still):
when(obj.process(argThat(tpc -> someLogic()))).thenReturn(someObj);
More often than not, however, if you just want to compare the class' data members, the built-in refEq matcher would do the trick:
ThirdParytClass expected = new ThirdParytClass();
// set the expected properties of expected
when(obj.process(refEq(expected))).thenReturn(someObj);
Mockito provides the captor feature that may help you to bypass limitations of equals() method because overriding equals() to make a test pass may be desirable but it is not always the case.
And besides, sometimes, equals() may not be overridable. It is your use case.
Here is a example code with an ArgumentCaptor :
#Mock
MyMockedClass myMock;
#Captor
ArgumentCaptor argCaptor;
#Test
public void yourTest() {
ThirdPartyClass myArgToPass = new ThirdPartyClass();
// call the object under test
...
//
Mockito.verify(myMock).process(argCaptor.capture());
// assert the value of the captor argument is the expected onoe
assertEquals(myArgToPass , argCaptor.getValue());
}

Mockito match specific Class argument

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

Matchers.any() for null value in Mockito

Suppose I am having this object objectDemo which calls to the method objectDemoMethod with 2 parameters String and null. Now I want to verify with Mockito that this method was called:
objectDemo.objectDemoMethod("SAMPLE_STRING", null);
I have written this:
Mockito.verify(objectDemo, Mockito.times(1)).objectDemoMethod(Matchers.any(String.class), null);
but it's giving an error:
Invalid use of argument matchers for null value.
Is there any another way to pass null value?
The error message you are getting is expected since you are using argument matcher for only one argument and not the other. From Matchers Javadoc:
If you are using argument matchers, all arguments have to be provided by matchers.
Therefore, the fix is to use a matcher for the second parameter of the method as well. In this case, it would be a matcher matching null. Depending on the version of Mockito and Java, you can have:
Starting with Mockito 2, you can use ArgumentMatchers.isNull(). This works with Java 8 and above:
verify(objectDemo, times(1)).objectDemoMethod(any(String.class), isNull());
Note that if you're running with Java 7 or older, you'll need an explicit cast to make this work, because the type inference in those versions of Java does not take into account the types of the method called:
verify(objectDemo, times(1)).objectDemoMethod(any(String.class), (String) isNull());
If you're using Mockito 1, you can use the Matchers.isNull(clazz) instead:
verify(objectDemo, times(1)).objectDemoMethod(any(String.class), isNull(String.class));
For the Java ≤ 7 or Mockito 1 cases, the examples uses a case where the second parameter was of type String: it would need to be replaced with the actual type of the method parameter.
isNull seems to be deprecated
With Java 8 this method will be removed in Mockito 3.0. This method is only used for generic friendliness to avoid casting, this is not anymore needed in Java 8.
I think you could use nullable:
public static <T> T nullable(Class<T> clazz)
You could use something like:
verify(objectDemo, times(1)).objectDemoMethod(any(String.class), nullable(String.class));
Just use:
Mockito.verify(objectDemo, Mockito.times(1)).objectDemoMethod(Matchers.any(String.class), (ClassName) isNull());
Above help me in java 8 version. Hope this will help you.
You can make use of Mockito's ArgumentMatchers class, like so:
Mockito.verify(objectDemo).objectDemoMethod(ArgumentMatchers.any(String.class), ArgumentMatchers.isNull());
Ran into this when using Mockito 2.28 and Mockito Kotlin 2.2
any() and isNull() weren't matching. However, eq(null) did finally match, so you might try that if you're in the same boat.

What's the difference between Mockito Matchers isA, any, eq, and same?

I am confused on what's the difference between them, and which one to choose in which case. Some difference might be obvious, like any and eq, but I'm including them all just to be sure.
I wonder about their differences because I came across this problem:
I have this POST method in a Controller class
public Response doSomething(#ResponseBody Request request) {
return someService.doSomething(request);
}
And would like to perform a unit test on that controller.
I have two versions. The first one is the simple one, like this
#Test
public void testDoSomething() {
//initialize ObjectMapper mapper
//initialize Request req and Response res
when(someServiceMock.doSomething(req)).thenReturn(res);
Response actualRes = someController.doSomething(req);
assertThat(actualRes, is(res));
}
But I wanted to use a MockMvc approach, like this one
#Test
public void testDoSomething() {
//initialize ObjectMapper mapper
//initialize Request req and Response res
when(someServiceMock.doSomething(any(Request.class))).thenReturn(res);
mockMvc.perform(post("/do/something")
.contentType(MediaType.APPLICATION_JSON)
.content(mapper.writeValueAsString(req))
)
.andExpect(status().isOk())
.andExpect(jsonPath("$message", is("done")));
}
Both work well. But I wanted my someServiceMock.doSomething() in the MockMvc approach to receive req, or at least an object that has the same variable values as req (not just any Request class), and return res, just like the first. I know that it's impossible using the MockMvc approach (or is it?), because the object passed in the actual call is always different from the object passed in the mock. Is there anyway I can achieve that? Or does it even make sense to do that? Or should I be satisfied using any(Request.class)? I've tried eq, same, but all of them fail.
any() checks absolutely nothing. Since Mockito 2.0, any(T.class) shares isA semantics to mean "any T" or properly "any instance of type T".
This is a change compared to Mockito 1.x, where any(T.class) checked absolutely nothing but saved a cast prior to Java 8: "Any kind object, not necessary of the given class. The class argument is provided only to avoid casting."
isA(T.class) checks that the argument instanceof T, implying it is non-null.
same(obj) checks that the argument refers to the same instance as obj, such that arg == obj is true.
eq(obj) checks that the argument equals obj according to its equals method. This is also the behavior if you pass in real values without using matchers.
Note that unless equals is overridden, you'll see the default Object.equals implementation, which would have the same behavior as same(obj).
If you need more exact customization, you can use an adapter for your own predicate:
For Mockito 1.x, use argThat with a custom Hamcrest Matcher<T> that selects exactly the objects you need.
For Mockito 2.0 and beyond, use Matchers.argThat with a custom org.mockito.ArgumentMatcher<T>, or MockitoHamcrest.argThat with a custom Hamcrest Matcher<T>.
You may also use refEq, which uses reflection to confirm object equality; Hamcrest has a similar implementation with SamePropertyValuesAs for public bean-style properties. Note that on GitHub issue #1800 proposes deprecating and removing refEq, and as in that issue you might prefer eq to better give your classes better encapsulation over their sense of equality.
If your Request.class implements equals, then you can use eq():
Bar bar = getBar();
when(fooService.fooFxn(eq(bar)).then...
The above when would activate on
fooService.fooFxn(otherBar);
if
otherBar.equals(bar);
Alternatively, if you want to the mock to work for some other subset of input (for instance, all Bars with Bar.getBarLength()>10), you could create a Matcher. I don't see this pattern too often, so usually I create the Matcher as a private class:
private static class BarMatcher extends BaseMatcher<Bar>{
...//constructors, descriptions, etc.
public boolean matches(Object otherBar){
//Checks, casts, etc.
return otherBar.getBarLength()>10;
}
}
You would then use this matcher as follows:
when(fooService.fooFxn(argThat(new BarMatcher())).then...
Hope that helps!

Categories