有没有办法使用mockito模拟静态方法?

时间:2015-08-11 15:48:35

标签: java unit-testing static mockito

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

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中使用的所有这些静态方法,但目前我找不到任何方法。你现在有吗?

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:0)

由于你无法覆盖静态方法,不能,你不能在Mockito中嘲笑它们。

答案 2 :(得分:0)

您应该/可以使用Singleton模式。

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

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

这是可行的,但它不是最优雅的解决方案,但静态调用首先并不是那么优雅。我正在回答,因为没有可能的方法来重构整个代码库(比如使用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);

这只需要您正在查看的课程中的一个小型重构,而无需触及项目的其余部分,同时实现您想要的目标。