Reputation: 5158
I understand you can't mock static methods using mockito. But the method I am trying to mock is not static but it has a call to static methods in it. So can I mock this method?
I get exception when I run the test. Is the call to the static method the reason for this exception?
The Class to be tested:
public class MyAction{
public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
MyService service = new MyService();
**form.setList(service.getRecords(searchRequest));**
}
}
Mocked class and method:
public class MyService{
public List getRecords(SearchRequest sr){
List returnList = new ArrayList();
MyDao dao = DAOFactory.getInstance().getDAO();---->Call to static method
// Some codes
return returnList;
}
}
Class with static method:
public class DAOFactory{
private static DAOFactory instance = new DAOFactory();
public static DAOFactory getInstance() {------> The static method
return instance;
}
}
My Test:
@Test
public void testSearch() throws Exception{
MyService service = mock(MyService.class);
MyAction action = new MyAction();
List<MyList> list = new ArrayList<MyList>();
when(service.getRecords(searchRequest)).thenReturn(list);
ActionForward forward = action.search(mapping, form, request, response);
}
This is the stack trace when I run the test. Please keep in mind that I have changed the names of the classes for simplicity.
Upvotes: 3
Views: 2920
Reputation: 28981
The problem is that your search
method cannot use the service mock, because it creates its own instance by MyService service = new MyClass();
. So you must refactor the MyAction
class to allow MyService
injection and inject a mock in it. Or use more heavy weapon - PowerMock.
Easiest and safest Refactoring
Use in your IDE "extract method" refactoring to extract construction "new MyClass()". So it will become:
public class MyAction{
public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
MyService service = getMyService();
**form.setList(service.getRecords(searchRequest));**
}
MyService getMyService() {
return new MyClass();
}
}
then in your unit test you could inject a mock by creating an inner subclass:
public class MyActionTest {
private MyService service = mock(MyService.class);
private MyAction action = new MyAction(){
@Override
MyService getMyService() {return service;}
};
@Test
public void testSearch() throws Exception{
List<MyList> list = new ArrayList<MyList>();
when(service.getRecords(searchRequest)).thenReturn(list);
ActionForward forward = action.search(mapping, form, request, response);
}
}
Upvotes: 6