Mockito.verify method contain boolean and argument captor - java

I don't know how can I use Mockito.verify in this case. How can I pass false to Mockito.verify? I try 2 different ways but it does not work.
public Sample someMethod(Sample s, boolean a){....}
#Test
public void test() {
...
verify(mock).someMethod(sampleCaptor.capture(), false));
verify(mock).someMethod(sampleCaptor.capture(), org.mockito.Matchers.eq(false)));
...
}

You have it right the second way:
verify(mock).someMethod(sampleCaptor.capture(), Matchers.eq(false));
When using Matchers (including ArgumentCaptor.capture), you have to use a Matcher for every value, because Matchers work via side-effects.
If the above doesn't work, you may be misusing matchers earlier in the method. It is sometimes helpful to explicitly call Mockito.validateMockitoUsage() immediately before your call to verify, to ensure that there's nothing wrong with Mockito's internal state. (Additional information about how it "does not work", including a minimal reproducible example, may be helpful in solving your specific case.)

Related

Is it possible to mock a method that is both static and void using Mockito?

I'm trying to avoid using PowerMockito here. We have legacy code which contains methods that are both static and void and there are tests which need to mock them. Is there a way to do it or is refactoring legacy code the only way here?
class MySample {
public static void sampleMethod(String argument){
//do something
}
}
If I use the general MockStatic syntax, it asks me to return something:
MockedStatic <MySample> sampleMock = Mockito.mockStatic( MySample.class );
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)));
Exception:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at com.mytests.Test.setMock(Test.java:35)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, which is not supported
3. you are stubbing the behaviour of another mock inside before 'thenReturn' instruction is completed
Edit: Please note that I'm looking to mock a method that is BOTH static and void.
What do you want to happen when the mocked method gets called?
The default behavior is that nothing happens. By calling sampleMock.when(), you indicated that you wanted to change from the default behavior to something else. Mockito is complaining because you didn't then follow that up with a call to then___() to specify what should happen instead.
There are a few different things I can think of that you might want to have happen:
1. Do nothing
As previously stated, this is the default behavior, so if this is all you want, you can just remove the second line and it should work. But, if you really need to have a when call (e.g. for argument capture), you can instead finish off the line with an empty thenAnswer:
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
.thenAnswer(invocation -> null);
2. Call the real method
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
.thenCallRealMethod();
3. Do something else
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
.thenAnswer(invocation -> {
// insert code to do something else here
return null;
});
4. Throw an exception
sampleMock.when(() -> MySample.sampleMethod(Mockito.any(String.class)))
.thenThrow(RuntimeException.class);
Update
As previously mentioned, the default behavior is to do nothing, but I learned it's also possible to specify an alternate default behavior by providing an Answer when creating the mock. For example, to have the default behavior call the real method instead:
MockedStatic <MySample> sampleMock = Mockito.mockStatic( MySample.class, Mockito.CALLS_REAL_METHODS );
But beware - as noted by Marc in this answer, the real method will still be called even if you override the default behavior! This may be fixed in the future; see Marc's answer for some good references
Adding #RunWith(PowerMockRunner.class) to your class header will prevent the throw of the aforementioned exception type!

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 "verify" checks current state, but does not reset mock invocations

I'm using Mockito in my JUnit tests. The test is an integration test, testing a whole scenario, thus there are many assertions and verify(mock)s in it.
My problem is, that I'm writing some production code, doing some assertions and then verify the mock which works, until there is an identical mock invocation. see the simplified code:
interface I {
void m1();
void m2();
}
// some decorator
class T implements I {
public T(I decorated) {
/*...*/
}
/* ... */
}
public void testInvalid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
t.m2();
assertEquals("m2", t.getLastMethod());
verify(m).m2();
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
// TooManyActualInvocations t.m1(): Wanted 1 time, but was 2 times ...
}
public void testValid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
t.m2();
assertEquals("m2", t.getLastMethod());
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m, times(2)).m1();
verify(m).m2();
}
One idea is to verify the mocks at the end, but let's say there is a small stupid implementation mistake which leads to invoking the method m1 twice and m2 once but not as I would expect it in testInvalid but in the end the test would pass. I want my test to fail early. How do I accomplish that?
Thank you.
Thanks to #Woozy Coder:
Didn't mentioned, that reset would also be an option, but since it has to be called between verify and the next equal stub call, it makes it hard to write "nice" and correct tests, I think. There should be two different mocking styles:
"postcondition" mocking as Mockito does it
"early" mocking which would be an implicit reset after a verify-block
something like:
earlyReset(m).after(
new Runnable() {
t.someMethodInvokingTwoStubs();
verify(m).someMethod1();
verify(m).someMethod2();
}
);
I am having a similar problem and decided to use clearInvocations() (arrived in Mockito 2.1)
https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/Mockito.html#clearInvocations-T...-
Using reset() has the drawback that you loose your stubbing as well, clearInvocations() only clears the invocations.
Mockito was written to avoid brittleness, such that verification can make the least-specific assertion possible to allow for implementations to evolve without changing the test. If it doesn't matter to your test system that you're calling these methods multiple times, then you shouldn't ask Mockito to check it.
Alternatives:
Use atLeast or atLeastOnce to ensure the call happened at all without worrying how many additional times the method is called.
If the call is stubbed to have return values, infer that the system works from state assertions about the data you've stubbed.
If you really need stub or verification behavior to change across a single test method, your mock may grow outside the scope of what Mockito does well. Use an Answer for a single method, or write a manual Fake that simulates the interconnected methods properly.

Why a boolean can be in some cases converted to a string, and in other cases not?

I used a method that took a String and I wanted to pass a primitive boolean. I expect it to take that boolean and convert it to a String containing either "true" or "false".
Assume the following method:
public void method(String input) { ... }
I first tried something like this:
boolean myBoolean = true;
method(myBoolean.toString());
This gave me an error during compilation. But then when I added following additional overloaded method, this worked again:
public void method(Boolean input) {
method(input);
}
I was confused to discover that in that case, calling method(myBoolean) worked just fine.
Why is this?
First thing to understand is that primitives do not have methods. At least not as of date, and might change with implementation of Project Valhalla. To be able to call the toString() on it, you will first require to box it either by autoboxing or by wrapping it explicitly.
Given a method public void takeString(String input) {}:
takeString(true) will fail, although
takeString(""+true) will work, as it is equivalent to
takeString(""+Boolean.valueOf(true).toString()), which works.
takeString(Boolean.valueOf(true).toString()) will work as well, but note that
takeString(Boolean.valueOf(true)) will fail again for the same reason as in (1).
It might be curious that in case (2), it was able to apply autoboxing and implicitly call the toString(), while it was not able to do so for (1).
But there is good reason for it, as in the case of (2), it is clear to the compiler that the method signature will have a parameter type of String, so it can do the needed implicit conversions. While for (1), it would be dangerous to do so given that we can have multiple overloaded versions of takeString. It just makes the compiler's job simpler, and avoids issues when the overloaded version would be added later on. It is safer to fail on (2).
Example, we do not want logic to suddenly change because we add following method: public void takeString(boolean input) {}.
Possibly you could consider adding following method:
public void takeString(Boolean b) {
takeString(b.toString());
}
The intent of "conversion-only" is clear here, and will reduce the chance of adding in additional unintended logic.
In that case, it might also be wiser to provide an overloaded version for the native boolean parameter to avoid surprises later on as the API evolves.
Then all your cases, except true.toString() will work. Seems like a case to ask to implement conversions in Java, the way we have them in Scala. That will avoid a lot of overload boilerplate.
Primitive types (boolean for example) do not have methods. That is why an error occured when you tried boolean.toString(). Wrapper classes than though (Boolean.toString() for example).
Now for the method, if your method is like this:
public void method(String s)
then you must have made another method like this:
public void method(boolean b)
to be able to perform method(boolean). Without the method(boolean b), your compiler would say method cannot be applied to boolean or something along those lines.

Categories