Mocking a Spy method with Mockito - java

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!

Related

Testing the same cases in a method called from different method in a Unit Test?

I have a private service method that is called from create and update methods in the same service. Normally we do not write Unit Test directly for the private method and I write the case in the method that calls this service method.
At this stage, I am confused that; I write all the test cases for the private method in the tests for create method.
1. In this scene, should I omit the same case for the private method when I write test method for the update method? Because in this case it seems to be writing redundant tests for the same case (calling it from create + calling it again from update method).
2. On the other hand, I am also thinking of that if I remove create or update method in the future, then calculate method tests will be removed. In this case, it may be better to write test cases related to calculate method in both of create and update methods.
Any idea regarding to this issue?
Here is a sample code if you need to explain something based on this scenario:
public void create(EmployeeRequest request) {
// code omitted
calculate();
}
public void update(UUID uuid, EmployeeRequest request) {
// code omitted
calculate();
}
private void calculate() {
// code omitted
}

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.

Mockito validates already verified invocations

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

How to mock/test method that returns void, possibly in Mockito

I came across a problem and I can't find an elegant solution.
So the problem is with a mock of Selenium web driver, and I dont know how should I test/mock void methods.
public void clickAndWait(String locator) {
if(isElementPresent(locator) == false) throw some exception;
selenium.clickAndWait(); //a problematic delegating call to selenium
}
So what I am asking is, how to properly test such a method, one test would be for exception being thrown, but how properly make test of that void method I delegate to?
The following code sample from this Mockito documentation illustrates how to mock a void method:
doThrow(new RuntimeException()).when(mockedList).clear();
// following throws RuntimeException:
mockedList.clear();
doAnswer(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(mock).method((SomeClass) anyObject());
The previous answers have been stressing on doing something (throwing an exception possibly) at every call. This way when you do something like :
doThrow(new RuntimeException()).when(mockedList).clear();
and then call the stubbed service (or logic) like :
mockedList.clear();
it will generate an exception. What if you want to test for a proper functioning of method maybe writing positive test case. Mocking a void returning method for such case could be done by :
doNothing().when(mockedList).clear();
which means that since you stubbed the clear() method for mockedList mock, you can be sure that this method is not going to effect the logic of the unit and still you can check the rest of the flow without generating an exception.
You can also use:
The method Mockito.verify(mock/spy) to check how many times the method has been called.
Or use the argument captor to see/check some parameters passed to the void method.
You can trow an exception on your method call, here is a small example how to do it:
doThrow(new RuntimeException()).when(mockedList).clear();
then you call mockedList.clear(); mocked method will throw an exception.
Or you can count how many times your method was called, here is a small example how to do it:
verify(mockedList, times(1)).clear();
In Java 8 this can be made a little cleaner
doAnswer((i) -> {
// Do stuff with i.getArguments() here
return null;
}).when(*mock*).*method*(*methodArguments*);
The return null; is important and without it the compile will fail with some fairly obscure errors as it won't be able to find a suitable override for doAnswer.

Categories

Resources