Mockito validates already verified invocations - java

static class Foo {
public void bar(int i) {}
}
#Test
public void foo() {
Foo f = Mockito.spy(new Foo());
f.bar(42);
Mockito.verify(f, Mockito.times(1)).bar(42);
f.bar(42);
Mockito.verify(f, Mockito.times(1)).bar(42);
}
causes org.mockito.exceptions.verification.TooManyActualInvocations (wanted 1 time, but was 2) on last line. Running it in debug shows, that InvocationMatcher ignores the fact that first invocation was already verified. And it does not depend on witch exactly matcher is passed into bar. Am I doing something wrong, or it is a bug of Mockito?

There is no bug. The implementors of the library thinks multiple invocations in a single test method is not a best practice. There two choices to overcome this issue:
Good one: use separate tests for each f.bar() invocations and test them independently.
Not a good one: use Mockito.reset(f) before the second invocation. It resets the state of the spied f; for instance if you have inserted a mock call like doThrow(new Exception).when(f).bar(45), it is reset after the reset() call. But the second verify works with times(1).

Related

Issue with PowerMockito verifyStatic() method for a static recursive function in Java

I am new to Mockito and PowerMockito. I have a test method where I use PowerMockito to mock a static recursive method. I need to verify that particular method is invoked 2 times, but the test case fails. Also the actual method is not hit.
This is the code.
Testing method:
public class Util {
public static void methodToTest(String a, String b) {
..............
methodToTest(c, d);
}
}
Test case :
public void testMethodToTest() {
PowerMockito.mockStatic(Util.class);
Util.methodToTest(e, f);
verifyStatic(Util.class, Mockito.times(2));
Util.methodToTest(Matchers.anyString(), Matchers.anyString());
}
But when I run the test it fails with the following error.
Wanted 2 times but was 1 time.
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:182)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:164)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:141)
Ideally with Util.methodToTest(e, f) call,it should call the actual methodToTest twice.
I debugged the code and then I noticed that Util.methodToTest(e, f) call does not go inside the actual method.
What is the issue in this code? How can I verify that this recursive method is getting called twice?
Powermock version - 1.7.4
The problem here is that you are invoking intercepted method from inside of spied/mocked object. Interception is made when call is made from the outside. So original call is "registered" but not the internal one.
I am not sure it is a bug or expected behavior, but I have ran into the same issue some time ago (but not with statics) and If I recall I redesigned the test.

Writing unit test for #Nonnull annotated parameter

I have a method like this one:
public void foo(#Nonnull String value) {...}
I would like to write a unit test to make sure foo() throws an NPE when value is null but I can't since the compiler refuses to compile the unit test when static null pointer flow analysis is enabled in IDE.
How do I make this test compile (in Eclipse with "Enable annotation-based null analysis" enabled):
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(null);
}
Note: In theory the static null pointer of the compiler should prevent cases like that. But there is nothing stopping someone from writing another module with the static flow analysis turned off and calling the method with null.
Common case: Big messy old project without flow analysis. I start with annotating some utility module. In that case, I'll have existing or new unit tests which check how the code behaves for all the modules which don't use flow analysis yet.
My guess is that I have to move those tests into an unchecked module and move them around as I spread flow analysis. That would work and fit well into the philosophy but it would be a lot of manual work.
To put it another way: I can't easily write a test which says "success when code doesn't compile" (I'd have to put code pieces into files, invoke the compiler from unit tests, check the output for errors ... not pretty). So how can I test easily that the code fails as it should when callers ignore #Nonnull?
Hiding null within a method does the trick:
public void foo(#NonNull String bar) {
Objects.requireNonNull(bar);
}
/** Trick the Java flow analysis to allow passing <code>null</code>
* for #Nonnull parameters.
*/
#SuppressWarnings("null")
public static <T> T giveNull() {
return null;
}
#Test(expected = NullPointerException.class)
public void testFoo() {
foo(giveNull());
}
The above compiles fine (and yes, double-checked - when using foo(null) my IDE gives me a compile error - so "null checking" is enabled).
In contrast to the solution given via comments, the above has the nice side effect to work for any kind of parameter type (but might probably require Java8 to get the type inference correct always).
And yes, the test passes (as written above), and fails when commenting out the Objects.requireNonNull() line.
Why not just use plain old reflection?
try {
YourClass.getMethod("foo", String.class).invoke(someInstance, null);
fail("Expected InvocationException with nested NPE");
} catch(InvocationException e) {
if (e.getCause() instanceof NullPointerException) {
return; // success
}
throw e; // let the test fail
}
Note that this can break unexpectedly when refactoring (you rename the method, change the order of method parameters, move method to new type).
Using assertThrows from Jupiter assertions I was able to test this:
public MethodName(#NonNull final param1 dao) {....
assertThrows(IllegalArgumentException.class, () -> new MethodName(null));
Here design by contract comes to picture. You can not provide null value parameter to a method annotated with notNull argument.
You can use a field which you initialize and then set to null in a set up method:
private String nullValue = ""; // set to null in clearNullValue()
#Before
public void clearNullValue() {
nullValue = null;
}
#Test(expected = NullPointerException.class)
public void test() {
T inst = ...
inst.foo(nullValue);
}
As in GhostCat's answer, the compiler is unable to know whether and when clearNullValue() is called and has to assume that the field is not null.

JUnit assertion to force a line to be executed

Is there any junit assertion, with which i can force a line to be executed?
For example:
doAnswer(new Answer<Void>() {
#SuppressWarnings("unchecked")
#Override
public Void answer(final InvocationOnMock invocation) throws Throwable {
Object[] arguments = invocation.getArguments();
Map<String, String> fieldMapActual = (Map<String, String>) arguments[0];
assertEquals(fieldMap, fieldMapActual);
**assertFailIfThisLineIsNotExecuted();**
return null;
}
}).when(x).myMethod(xxx);
As i simulate the behaviour of myMethod, the method answer from the anonymous inner type will be executed at runtime of the myMethod (not at runtime of junit test), if myMethod will be called with the intended value/parameter.
In order to assert that the method is called, i must additionally define a verify (otherwise my test would still run even if the method is not called).
verify(x).myMethod(xxx);
If i had a chance to write sth like assertFailIfThisLineIsNotExecuted in the answer method, i would not have to define an extra verify. So again, Is there any junit assertion, with which i can force a line to be executed? Opposite of fail() so to speak, without immediately defining the method as "successful".
If you want to make sure that a certain line of your test is being executed, use a boolean flag:
final boolean[] wasExecuted = { false };
...
wasExecuted[0] = true;
...
assertTrue("Some code wasn't executed", wasExecuted);
But my gut feeling is that you're trying to solve a different problem.
The verify says "This method must have been called". It doesn't matter if you mocked an answer or not. So this is the approach that you should use.
I'm using my flag approach only when I can't create a mock for some reason. If that happens, I extend the class under test in my test code and add the flag.
The advantage of the flag over verify is that the flag documents in which place I expect the code to be (you can have the IDE search all places where the flag is used). verify() is not that easy to locate when it fails.
verify(x).myMethod(xxx); should be what you want. It also expresses intent.
assertFailIfThisLineIsNotExecuted() would also be a single line of code (so how would it be "better" than verify?), it's not supported by JUnit, you would have to write code to get a good error message, etc.

Mocking a Spy method with Mockito

I am writing a unit test for a FizzConfigurator class that looks like:
public class FizzConfigurator {
public void doFoo(String msg) {
doWidget(msg, Config.ALWAYS);
}
public void doBar(String msg) {
doWidget(msg, Config.NEVER);
}
public void doBuzz(String msg) {
doWidget(msg, Config.SOMETIMES);
}
public void doWidget(String msg, Config cfg) {
// Does a bunch of stuff and hits a database.
}
}
I'd like to write a simple unit test that stubs the doWidget(String,Config) method (so that it doesn't actually fire and hit the database), but that allows me to verify that calling doBuzz(String) ends up executing doWidget. Mockito seems like the right tool for the job here.
public class FizzConfiguratorTest {
#Test
public void callingDoBuzzAlsoCallsDoWidget() {
FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
Mockito.when(fixture.doWidget(Mockito.anyString(), Config.ALWAYS)).
thenThrow(new RuntimeException());
try {
fixture.doBuzz("This should throw.");
// We should never get here. Calling doBuzz should invoke our
// stubbed doWidget, which throws an exception.
Assert.fail();
} catch(RuntimeException rte) {
return; // Test passed.
}
}
}
This seems like a good gameplan (to me at least). But when I actually go to code it up, I get the following compiler error on the 2nd line inside the test method (the Mockito.when(...) line:
The method when(T) in the type Mockito is not applicable for the arguments (void)
I see that Mockito can't mock a method that returns void. So I ask:
Am I approaching this test setup correctly? Or is there a better, Mockito-recommended, way of testing that doBuzz calls doWidget under the hood? And
What can I do about mocking/stubbing doWidget as it is the most critical method of my entire FizzConfigurator class?
I wouldn't use exceptions to test that, but verifications. And another problem is that you can't use when() with methods returning void.
Here's how I would do it:
FizzConfigurator fixture = Mockito.spy(new FizzConfigurator());
doNothing().when(fixture).doWidget(Mockito.anyString(), Mockito.<Config>any()));
fixture.doBuzz("some string");
Mockito.verify(fixture).doWidget("some string", Config.SOMETIMES);
This isn't a direct answer to the question, but I ran across it when trying to troubleshoot my problem and haven't since found a more relevant question.
If you're trying to stub/mock an object marked as Spy, Mockito only picks up the stubs if they're created using the do...when convention as hinted at by JB Nizet:
doReturn(Set.of(...)).when(mySpy).getSomething(...);
It wasn't being picked up by:
when(mySpy.getSomething(...)).thenReturn(Set.of(...));
Which matches the comment in MockHandlerImpl::handle:
// stubbing voids with doThrow() or doAnswer() style
This is a clear sign that doWidget method should belong to another class which FizzConfigurator would depend on.
In your test, this new dependency would be a mock, and you could easily verify if its method was called with verify.
In my case, for the method I was trying to stub, I was passing in incorrect matchers.
My method signature (for the super class method I was trying to stub): String, Object.
I was passing in:
myMethod("string", Mockito.nullable(ClassType.class)) and getting:
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 if completed
When using a matcher in another parameter, we also need to use one for the string:
myMethod(eq("string"), Mockito.nullable(ClassType.class))
Hope this helps!

Mockito acts strangely when I assign multiple custom matchers to a single method

I'm wanting to use two custom matchers for a single method. Basically, if I pass the method VALUE_A, I want it to return RESULT_A, and if I pass it VALUE_B, I want it to return RESULT_B. So here's a code excerpt :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher to MockHtable.get()
//When this happens, the value of the get argument is null, so this method throws an NPE
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
class IsEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
return !(Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key)));
}
}
[...]
//This line executes just fine
Mockito.when(mockHTable.get(Mockito.argThat(new IsNonEmpty()))).thenReturn(dbResult);
[...]
//This line calls IsNonEmpty.matches() for some reason. IsNonEmpty.matches() throws an NPE
Mockito.when(mockHTable.get(Mockito.argThat(new IsEmpty()))).thenReturn(emptyResult);
When I assign the IsEmpty custom matcher to mockHTable.get() method, it calls the IsNonEmpty.matches() function. No idea why it's doing this. So I change the IsNonEmpty class to this :
class IsNonEmpty extends ArgumentMatcher<Get> {
public boolean matches(Object get) {
//For some reason, this method is called when I assign the IsEmpty matcher. Weird, no?
if(get == null) {
return false;
}
return Arrays.equals(((Get) get).getRow(), SERIALIZATION_HELPER.getValidBytes(key));
}
}
and then everything works just fine! IsNonEmpty.matches() is still called when I assign the IsEmpty matcher to the mockHTable.get() function, but my matchers work exactly how they should.
So what's the deal? Why does this happen? Is my work-around an adequate way to compensate for this quirky behavior, or am I Doing It Wrong?
The reason why IsNonEmpty.matches() gets called on the second line of stubbing is that the Mockito.argThat(new IsEmpty()) returns null, which is then passed to mockHTable.get(). This call has to be checked against the earlier stubbing, to see whether it's a match; and that means calling IsNonEmpty.matches().
I'm not sure why this makes your test fail - it's hard to tell without seeing all of the code.
But, I would seriously recommend using doReturn...when instead of when...thenReturn whenever you have to stub the same mock more than once. You won't encounter issues like this if you do. In fact, I prefer to use doReturn...when in preference to when...thenReturn always (and similarly doThrow and doAnswer), although most people prefer when...thenReturn.
Re-writing one of your stubbing lines with the doReturn...when syntax looks like the following. The other is similar.
Mockito.doReturn(dbResult).when(mockHTable).get(Mockito.argThat(new IsNonEmpty()));
Lastly, a plea, on behalf of the Mockito development team (of which I am a member). If you think there is a bug in Mockito here - and from your description, I think there may well be - please EITHER
send a message to the Mockito mailing group (mockito#googlegroups.com) OR
raise an issue on the Mockito issues list (http://code.google.com/p/mockito/issues/list).
It's useful to the Mockito team if you can actually post a complete example, rather than just what you think the key lines are - sometimes the cause of a Mockito problem is in quite an unexpected place.

Categories

Resources