You are here
Spying with Mockito - to call or not to call a method
The other day a weird feature of the testing library Mockito tricked me. Allthough the behavior is mentioned in the documentation, it can not be bad to point it out here. Maybe this article spares someones time debugging his code.
I wanted to write a unit test for the class Controller. Controller uses a method of Blo, a Business Logic Object, to perform its tasks:
public class Controller { Blo blo; public Controller(Blo blo) { this.blo = blo; } public int run() { // do important stuff here return blo.doSomeStuff(); } }
public class Blo { public int doSomeStuff() { return 42; } // other important methods }
To unit-test run() in Controller, I have to decouple it from the real Blo. Otherwise the test would be an integration test instead of a unit test because Blo is also tested. Further, I want Blo to behave normally except for the one method I need for my test. That so called partial mocking can be done using Mockitos spy- method:
public class ControllerTest { @Test final Blo bloMock = spy(new Blo()); // mocking methods of the spy will be done here in just a moment ... Controller s = new Controller(bloMock); assertEquals(1, s.run()); } }
So here is where I tricked myself. There are two ways to mock the method doSomeStuff() to return a 1 instead of the only true answer 42:
when(bloMock.doSomeStuff()).thenReturn(1);
and
doReturn(1).when(bloMock).doSomeStuff();
The very important difference is that the first option will actually call the doSomeStuff()- method while the second will not. Both will cause doSomeStuff() to return the desired 1.
So, why is this important? Imagine you have some side effects in doSomeStuff() that should not be called when your test is executed. That could be the reason why you mocked it in the first place. In my example code, that side effect is just printing a message, but it could be an important state change, the change of another class or whatever.
I hope some people can save time tracking that behavior by reading this article and remembering the difference between the two options.
Comments
spy
the spy feature is not working basically lets say i spy on an object and i want to stub a method of that object but spy is invoking the real method itself. For example
Object obj = new Object();
Object spy = spy(obj);
doReturn(true).when(spy).method();
when you do this ..it is actually invoking and calling the real method.
any idea why
Hello Thai,
Hello Thai,
I just wrote the following two classes using JUnit 4.11 and Mockito 1.9.5:
This proves my point of the article: the second call will not cause System.out to print something.
Can you confirm this with the given code?
So long,
Steven
Thanks Steven , it is userful
Thanks Steven , it is userful answer ! :D
Can't we mock object Blo
Can't we mock object Blo object int the constructor from unit testing,by creating the class by passingt a Mcoked Blo object?
Yes ...
That is what I've done in line 5 in the second code block. Is that what you mean?
spy() vs. mock()
spy() and mock() are two different things. The OP asked if you could mock() instead of spy(), and the answer is YES: you could do that to solve the same problem potentially. spy() is used when you want the real code of the class you are spying on to do its job, but be able to intercept method calls and return values. mock() is used to make a new class that has the same interface as the class you are mocking, but with NO code inside... so even if blo.doSomething() was called on the mocked class, it would do nothing no matter how you set it up.
Thanks
Thanks Steven, this article helped!
Many thanks
Thank you for sharing this, I spent hours trying to get partial mocking to work without this first call to real method (causing NPE in my case...).
Thanks a lot, you saved me
PowerMockito.doReturn("user").when(Util.class,"getUserName");
the result is that the actual "Util.getUserName()" method is called. The same behavior if i use "Powermockito.when.thenReturn" way. The same behavior if i use "Powermockito.stub(method()).thenReturn".
PowerMockito.doReturn("user").when(Util.class);
Great this article helped you
Great this article helped you! And thanks a lot for your comment :) Have fun!
Re: spying with mockito - to call or not to call a method
It seems that the above is true for non-private methods.
Private methods are being invoked in both cases, at least in my experience.
So how do I prevent private
So how do I prevent private method from being called??
Re: Call private method
Hi Magie! Could you explain your question in more detail?
mock Private static
Hi how can in mock a private static method in a class.
and also wats the difference between
A a = PowerMockito.spy(new A())
and
PowerMockito.spy(A.class)
Hi Sreenath,
Hi Sreenath,
I didn't use PowerMockito, sorry. I know it's capable to mock private static methods, but I try to prevent doing this because it is a pretty big hack. ;)
Have fun,
Steven
I lost an hour but then I
I lost an hour but then I saved many more with this! Thanks!!!
Thanks for sharing!!
I was running into the same issue, and your entry has saved me from getting crazy on it.
Besten Dank, und Beste Grüße aus nähe dein Bild :)
Great it saved you time,
Great it saved you time, danke für das nette Kommentar! :)
Thank you! It solved my
Thank you! It solved my problem. And now I realize that many of my methods are called while testing, while I was sure that they are purely mocked.
Thank you. Very useful
Thank you. Very useful information.
literally,you save my day,the
literally,you save my day,the issue has drived me crazy!!
Mocking new object inside a method
Thanks for nice tips... How to mock something like this : -
Class A {
public void foo() {
Cookie cookie = new BasicCookie();
....
...
....
// Some basic logic
for(Cookie currentCookie : cookie.getListCookies() {
// Some basic logic
}
}
}
Powermock
Have you tried Powermock (https://github.com/powermock/powermock) ?