如何用 mockito 模拟静态方法来做单元测试

How to mock the static method with mockito to do unit test

我有这样的方法

 public Response post(String json) {

   EventList list = Recorder.getRecorders();
   if (null == list || list.isEmpty()) {
     throw new ServiceUnavailableException("An Recorder is either not configured");
  }
  String targetIUrl = list.getNext().getBase();
  String targetV2Url = targetUrl + "/v2";

 // other processes......
}
  1. 我想模拟 Recorder.getRecorder() 并执行 when(Recorder.getRecorder()).thenReturn(null) 之类的操作并测试是否抛出 503 异常。但是 getRecorder() 是一个静态方法。我知道 Mockito 不能模拟静态方法,但我仍然想知道是否可以更改一些代码,使其在不使用 Powermock 或其他库的情况下可测试。

  2. 如果我mock Recorder,是不是要把方法改成post(String json, Recorder recorder)?否则,我怎样才能使这个模拟与方法交互?

如果您想在不使用模拟静态方法的库(例如 Powermock)的情况下模拟 getRecorders() 行为,那么您必须从 post() 内部提取静态调用。为此有几个选项:

  1. EventList传递给post()

    public post(String json, EventList list) {
        ...
    }
    
  2. EventList注入包含post()

    的class
    public class TheOneThatContainsThePostMethod {
        private EventList eventList;
    
        public TheOneThatContainsThePostMethod(EventList eventList) {
            this.eventList = eventList;
        }
    
        public post(String json) {
            if (null == this.eventList || this.eventList.isEmpty()) {
                throw new ServiceUnavailableException("An Recorder is either not configured");
            }
        }
    }
    
  3. 将静态方法调用隐藏在另一个class中并将thatclass的实例注入post()或class 包含 post()。例如:

    public class RecorderFactory {
        public EventList get() {
            return Recorder.getRecorders();
        }
    }
    
    public class TheOneThatContainsThePostMethod {
        private RecorderFactory recorderFactory;
    
        public TheOneThatContainsThePostMethod(RecorderFactory recorderFactory) {
            this.recorderFactory = recorderFactory;
        }
    
        public post(String json) {
            EventList list = recorderFactory.getRecorders();
            ...
        }
    }
    
    // Or ...
    
    public post(String json, RecorderFactory recorderFactory) {
        EventList list = recorderFactory.getRecorders();
        ...
    }
    

使用前两种方法,您的测试可以简单地调用 post() 提供 (1) null EventList; (2) 一个空的 EventList ...从而允许您测试 'throw a 503 exception' 行为。

使用第三种方法,您可以使用 Mockito 模拟 RecorderFactory 到 return 的行为 (1) null EventList; (2) 一个空的 EventList ...从而允许您测试 'throw a 503 exception' 行为。