Matchers.any() for null value in Mockito - java

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.

Related

Mockito answer is getting invoked only once

I am trying to mock spring's applicationContext.getBean(String, Class) method in below manner -
when(applicationContext.getBean(Mockito.anyString(), Mockito.eq(SomeClass.class))).thenAnswer(
new Answer<SomeClass>() {
#Override
public SomeClass answer(InvocationOnMock invocation) throws Throwable {
// doing some stuff and returning the object of SomeClass
}
});
The scenario is that, the applicationContext.getBean method will be called a number of times, each time a with different strings but the same class (SomeClass.class).
The problem I am getting here is that the answer is getting invoked for the very first invocation of getBean method. With each subsequent invocation of getBean I am getting below exception -
******org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));******
Any idea, if I am missing something ?
#Kshitij
I have faced same issue in my previous project. I came across this below doc:
http://static.javadoc.io/org.mockito/mockito-core/2.16.0/org/mockito/Mockito.html#resetting_mocks
Under section 17 it is explained how to use reset()
Example: Let's say we have EvenOddService which finds whether number is even or odd then Test case with reset() will look like:
when(evenOddService.isEven(20)).thenReturn(true);
Assert.assertEquals(evenOddController.isEven(20), true);
//allows to reuse the mock
reset(evenOddService);
Assert.assertEquals(evenOddController.isEven(20), true);
Hope this helps :).
When using Mockito, you need to tell him how many times you will call your mock. You need to make as many when calls as you will need. For instance, if you know you'll test your method three times, you need to declare three separate when statements.
PS: I used Mockito for a bit only, it is possible that there is a solution to tell Mockito to use the same Answer multiple times in a row.
EDIT
Olivier Grégoire pointed out in the comments that you can use a single when call, but call thenAnswer multiple times. It is more elegant this way.
I've added this to my test class:
#AfterEach
public void resetMock(){
Mockito.reset(myMockedService);
}

Mockito.any returns null

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.

Mockito verifies wrong overloaded method

I'm trying to write a unit test for a class that uses as a dependency an AsynchronousSocketChannel:
final AsynchronousSocketChannel channel = mock(AsynchronousSocketChannel.class);
final Client client = new Client(channel);
client.read();
verify(channel).read(isA(ByteBuffer.class), eq(client), isA(CompletionHandler.class));
However, I'm receiving the following error:
Invalid use of argument matchers!
5 matchers expected, 3 recorded:
This happens because AsynchronousSocketChannel.read has 4 different overloaded versions, and for some reason verify keeps choosing the one with 5 arguments, even if the matchers I'm passing match the version with read(ByteBuffer dst, A attachment, CompletionHandler<Integer,? super A> handler).
In this answer it's suggested that this could really be a problem with the actual compiler, and that it's possible to instruct the compiler to choose the right overloaded method with something like
verify(channel).read(
ArgumentMatchers.<ByteBuffer>isA(ByteBuffer.class),
ArgumentMatchers.<Client>eq(client),
ArgumentMatchers.<CompletionHandler>isA(CompletionHandler.class)
);
but doing this I keep getting the same error.
Any idea if it's possible to make this work? Otherwise I believe I could just use the 5 params overloading, passing null as the additional 2 params, but it would be a bit like a hack to me.
You're trying to set expectations on a final method.
public final <A> void read(ByteBuffer dst,
A attachment,
CompletionHandler<Integer,? super A> handler)
Mockito can't override that method in the mock, so it's actually calling the real method. And that method is calling through to the overload with 5 parameters, and it's in that method where it is interacting with the mockito framework.
If you can construct the Client with an AsynchronousByteChannel instead of a AsynchronousSocketChannel, you could use that instead. This would work as you expect, because the 3-parameter overload isn't final on that class.
Otherwise, all you can do (with Mockito) is to set the expectations of what that 5-parameter overload will be called with.

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

Java - passing null as an argument to print()

I want to know why the below code doesn't work :
System.out.print(null);
response.getWriter().print(null);
But the below ones work :
String s = null;
System.out.print(s);
response.getWriter().print(s);
Whats the difference between passing a null as compared to passing a reference as null ?
EDITED : Doesn't work fore mentioned indicates to compilation error .
This is because you can pass an Object or a String. Since null can fit in both, the compiler doesn't know which method to use, leading to compile error.
Methods definitions:
System.out.print(Object)
System.out.print(String)
Instead, if you provide an Object or a String variable (even if it has null value), the compiler would know which method to use.
EDIT: This is better explained in this answer. As to the internal link pointing to the Java specification, you can read it here, and this case would suit here:
The informal intuition is that one method is more specific than another **if any invocation handled by the first method could be passed on to the other one without a compile-time type error.
It is possible that no method is the most specific, because there are two or more methods that are maximally specific.
It's because System.out.println() expects something with a type. null doesn't have a type, and therefore it can't be output on it's own. This is shown by:
Doesn't work:
System.out.println(null);
Works:
System.out.println((String)null);
System.out.println((char[])null);
System.out.println((Object)null);
It's the compiler type-checking the parameters of the method call.
Thank you all for your answers . From your inputs , I compiled the answer myself . It seems the call System.out.print(null) is ambiguous to compiler because print(null) here will find the two best specific matches i.e. print(String) and print(char[]) . So compiler is unable to determine which method to call here .
Small example will be :
private void methodCall(String str) {
}
private void methodCall(char[] ch){
}
Now this code becomes ambigious : methodCall(null) .

Categories