有什么方法可以使用 mockito 模拟静态方法吗?

Are there any ways to mock static methods using mockito?

我想为我的更改编写测试,但遇到了问题 - 更改是在静态方法中进行的。 代码看起来像这样

class GlobalData {
static boolean doSomething(...){...}
static xxx A() {...}
static yyy B() {...}
static void C() {
xxx a = A();
yyy b = B();

if (doSomething(a, b))
{
   a.xyz(b,42);
   ... my coode i want to test....
}
}

我想要的是模拟方法 A 和 B 以及 doSomething 以及方法 C 中使用的所有这些静态方法,但目前我找不到任何方法来做到这一点。你现在有吗?

因为你不能覆盖静态方法,不,你不能在 Mockito 中模拟它们。

您should/could使用单例模式。

基本上所有的静态方法都会调用一个内部私有对象来执行实际逻辑(称为 实例)。

如果这样做,您可以提供一个受保护的静态方法setInstance。在测试期间,您创建了一个模拟的 实例 并将其设置为静态 class.

这是可行的,但它不是最优雅的解决方案,但静态调用首先并不是那么优雅。我正在回答,因为无法重构整个代码库(例如使用 Dependency Injection

例如:

class GlobalData {
    //private object that does all the actual logic
    private static GlobalData instance = new GlobalData();

    //constructor is private so no one can call it
    private GlobalData() {

    }

    //delegate the static call to the internal instance
    static boolean doSomething(...){ return instance._doSomething(); }

    //use underscore to keep similar name but avoid ambiguous call
    private boolean _doSomething(...){ ... }

    //same here
    static xxx A() { return instance._A(); }
    private xxx _A() {...}

    //this is not public, so must be called from the same package
    //since the constructor is private, no one will be able to create a GlobalData
    //except for mockito
    static void setInstance(GlobalData instance) {
        GlobalData.instance = instance;
    }
}

然后在你的测试中(应该在同一个包中):

GlobalData instanceMocked = mock(GlobalData.class);
//we mock the methods with underscore, as they are the instance methods, and
//not the class methods
when(instanceMocked._A()).thenReturn(whatever);
when(instanceMocked._doSomething()).thenReturn(whatever);
GlobalData.setInstance(instanceMocked);

这只需要对您正在查看的 class 进行少量重构,而无需触及项目的其余部分,同时实现您想要的。

考虑使用 powerMock。它在 Mockito 上有一个名为 'powerMockito' 的扩展。它还使您能够模拟静态方法。 https://github.com/jayway/powermock/wiki/MockitoUsage