I am working on spring based project and writing unit test case using JUnit + Mockito. I am facing a problem while stubbing boolean value to a private method of same test class (after changing access level to public, still I have failed to stub the boolean value).
Below code snippet shows the simulation of same problem
class ABC {
public String method1(User userObj){
String result = "";
if(!isValidUser(userObj.getSessionID())){
return "InvalidUser";
} else {
// execute some logic
}
return result;
}
private boolean isValidUser(String sessionId) {
// Here it calls some other class to validate the user
if (sessionId == null || UserSessionPool.getInstance().getSessionUser(sessionId) == null) {
return false;
} else {
return true;
}
}
}
Here, I would like to write a test case for method1(). In class ABC I have a method called isValidUser()
which helps to identify the user with in a session by looking into a global session pool which holds all logged-in used details i.e. UserSessionPool.getInstance().getSessionUser(sessionId)
.
While testing method1(), the moment test controller triggers isValidUser(userObj.getSessionID())
I would like to return true
from isValidUser()
method, so that I can continue to test rest of the implementation logic.
So far I have tried following ways using spy and mocked object to call the isValidUser()
method and try to return true but nothing worked well.
Using PowerMockito
PowerMockito.doNothing().when(spyed_ABC_ClassObject, "isValidUser", true);
or
PowerMockito.doReturn(true).when(cntrl, "isValidUser", Mockito.anyString());
Using Whitebox
Whitebox.invokeMethod(spyed_ABC_ClassObject, "isValidUser", Mockito.anyString());
Using Mockito.when
when(spyed_ABC_ClassObject.isValidUser(Mockito.anyString())).thenReturn(true);
or
Mockito.doNothing().when(spyed_ABC_ClassObject).isValidUser(Mockito.anyString());
For Mockito, there is no direct support to mock private and static methods. In order to test private methods, you will need to refactor the code to change the access to protected (or package) and you will have to avoid static/final methods.
Mocking is done when you invoke methods of a class that has external communication like database calls or rest calls. Through mocking you can explicitly define the return value of methods without actually executing the steps of the method.
A stub is a fake class that comes with preprogrammed return values. It's injected into the class under test to give you absolute control over what's being tested as input. A typical stub is a database connection that allows you to mimic any scenario without having a real database.
The other answer is: fix your design instead of turning to the big PowerMock hammer.
Yes, PowerMock allows you to mock static methods. But you should understand: static is an abnormality in good OO design. You only use it when you have very good reasons. As it leads to tight coupling between your classes, and surprise: it breaks your ability to write reasonable unit tests. Yes, PowerMock works; but sometimes, it does not. When your classes grow, and you do more and more things "statically", because, you know, PowerMock will do the job ... be prepared for bizarre fails at some point, that can take hours to hunt down; without ever finding real bugs in your production code.
So, consider an alternative:
In that sense: you simply created hard to test code. Now you intend to fix that using PowerMock. The other way (much more reasonable in my eyes) is to learn how to write testable code in the first place. Here is a good starting point for that.
Can you please try this out.
@Before
public void setUp() {
UserSessionPool mockConnectionPool = Mockito.mock(UserSessionPool.class);
}
@Test
public void testName() throws Exception {
//given
PowerMockito.mockStatic(UserSessionPool.class);
BDDMockito.given(UserSessionPool.getInstance()(...)).willReturn(mockConnectionPool);
Mockito.when(mockConnectionPool.getSessionUser(Mockito.anylong())).thenReturn(something);
//then
PowerMockito.verifyStatic();
}
Hope this helps. Happy coding !
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With