使用PowerMock模拟单例的getInstance

时间:2016-11-15 17:58:27

标签: java unit-testing mockito powermock easymock

我有以下Singleton返回不同类的实例。我想在返回的实例对象上模拟方法。我一直在阅读有关最终班级和单身人士的PowerMock模拟功能,但我不知道我的案件是否属于这些。我很欣赏一些建议。

public final class SomeWrapper {
    private MyActualObject MyActualObject;
    private static final SomeWrapper instance = new SomeWrapper();

    private SomeWrapper() {
        // singleton
    }

    public static SomeWrapper getInstance() {
        return instance;
    }

    public void setMyActualObject(MyActualObject MyActualObject) {
        if(this.MyActualObject == null) {
            this.MyActualObject = MyActualObject;
        } else {
            throw new UnsupportedOperationException("MyActualObject is already set, cannot reset.");
        }
    }

    public MyActualObject getMyActualObject() {
        return MyActualObject;
    }
}

所以现在在我的单元测试中,我想嘲笑以下几行:

when(SomeWrapper.getInstance().getMyActualObject().isActive()).thenReturn(false);

我应该模拟SomeWrapper和MyActualObject吗?任何代码示例作为指导?

2 个答案:

答案 0 :(得分:1)

这里的要点是:你编写了难以测试的代码。是的,PowerMock可以帮助"修复"但是,您可能更愿意简单地重新编写生产代码,以便更容易测试。

例如,通过添加包受保护的构造函数,例如:

SomeWrapper(MyActualObject myActualObject) {
  this.MyActualObject = myActualObject;
}

这将允许您创建一个SomeWrapper类的实例,该实例接收完全有效的MyActualObject实例。

从这个意义上讲:您可能想了解如何创建实际为testable的生产代码。

答案 1 :(得分:0)

使用以下Mockito和PowerMock版本:

testImplementation 'org.mockito:mockito-core:2.23.4'
testImplementation 'org.powermock:powermock-module-junit4:2.0.0-beta.5'
testImplementation 'org.powermock:powermock-api-mockito2:2.0.0-beta.5'

您可以使用MainApplicationPowerMock.mockStatic()机制来模拟android when()单例实例,例如:

private MainApplication mApplication;

@NonNull
protected MainApplication getApplication() {
    if (mApplication == null) {
        mApplication = PowerMockito.mock(MainApplication.class);

        PowerMockito.mockStatic(MainApplication.class);
        PowerMockito.when(MainApplication.getInstance()).thenReturn(mApplication);
        PowerMockito.when(mApplication.getBaseContext()).thenReturn(mApplication);
        PowerMockito.when(mApplication.getApplicationContext()).thenReturn(mApplication);
    }
    return mApplication;
}

模拟私有构造函数可能很棘手-您可以通过在thenReturn()调用中使用替代类来尝试本文中建议的方法: SO - Mocking Private Constructor