Can you mock a non-stationary method that calls a static method using Mockito?

I understand that you cannot mock static methods using mockito. But the method I'm trying to mock is not static, but there is a call to static methods in it. Can I mock this method?

I am getting an exception when I run the test. Is the call to a static method causing this exception?

Class for testing:

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));**
        }
    }

      

Dedicated 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 the test is running. Please keep in mind that I have changed the class names for simplicity. enter image description here

+3


source to share


1 answer


The problem is that your method search

cannot use the service layout because it creates its own instance MyService service = new MyClass();

. Therefore, you must refactor the class MyAction

to allow MyService

injection and inject layout into it. Or use a heavier weapon - PowerMock.

The easiest and safest refactoring

Use the "extract method" in your IDE repository to extract the "new MyClass ()" construct. So it will be:



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 unit test you can inject 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);        
    }

}

      

+6


source







All Articles