你能模拟一个使用Mockito调用静态方法的非静态方法吗?

时间:2013-01-24 20:43:24

标签: java unit-testing mocking tdd mockito

我知道你不能使用mockito来模拟静态方法。但我试图模拟的方法不是静态的,而是在其中调用静态方法。那我可以嘲笑这个方法吗?

我在运行测试时遇到异常。调用静态方法是否有这种异常的原因?

要测试的课程:

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

模拟课程和方法:

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

使用静态方法的类:

public class DAOFactory{
        private static DAOFactory instance = new DAOFactory();

         public static DAOFactory getInstance() {------> The static method
            return instance;
        }       
    }

我的测试:

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

这是我运行测试时的堆栈跟踪。请记住,为了简单起见,我更改了类的名称。 enter image description here

1 个答案:

答案 0 :(得分:6)

问题是您的search方法无法使用服务模拟,因为它会MyService service = new MyClass();创建自己的实例。因此,您必须重构MyAction类以允许MyService注入并在其中注入模拟。或者使用更重的武器 - PowerMock。

最简单,最安全的重构

在IDE中使用“提取方法”重构以提取构造“new MyClass()”。所以它会变成:

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

    }

然后在你的单元测试中你可以通过创建一个内部子类来注入一个模拟:

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

}