你怎么投RuntimeEnvironment.application?

How do you cast RuntimeEnvironment.application?

运行Robolectric测试时,RuntimeEnvironment.application的类型由你的配置决定。假设我将 RoboApplication.class 配置为我的测试应用程序,我可以将 RuntimeEnvironment.application 强制转换为我的类型。

RoboApplication app = (RoboApplication) RuntimeEnvironment.application;
app.doSomething();

但是,一旦我集成了 PowerMock,转换行就会失败

java.lang.ClassCastException: RoboApplication cannot be cast to RoboApplication

我该如何解决这个问题?

这是一个问题,因为 PowerMock 和 Robolectric 由于使用它们自己的 classloader.

而相互不兼容

即使名称相同,Class 对象实际上并不相同:Robolectric 和 PowerMock 都通过 custom [=40] 加载测试来工作=]装载机。这些 classloader 更改了有问题的 classes,允许您替换 static/final Android 系统 classes 和方法 [Robolectric] 或所有static/final classes [PowerMock]。这是 PowerMock 和 Robolectric 都依赖于拥有自己的 JUnit4 Runner 的部分原因:这样他们就可以从自己的修改 classloader 加载适当的 classes。

因此,无法将实例转换为彼此的 classes,即使它们具有相同的名称并且源自 来自同一来源文件:每个框架都可以更改 class 实现,因此它们不一定相互兼容。

您需要选择一个框架或另一个框架:使用 Robolectric shadows,可能直接使用 EasyMock 或 Mockito,或者使用 PowerMock 手动存根 Android 基础设施调用。

另请参阅:

  • ClassCastException when casting to the same class
  • cast across classloader?

我还需要应用程序参考才能启动 Dagger2 模块。经过几次尝试并得到相同的强制转换异常错误后,我按如下方式制作了我的应用程序

public class App extends Application {

private static AppComponent appComponent;

@Override
public void onCreate() {
    super.onCreate();

    if( appComponent==null ){

        appComponent = DaggerAppComponent.builder().appModule(new AppModule(this)).build();
    }
}

public static AppComponent getAppComponent() {
    return appComponent;
}

public static void setAppComponent(AppComponent component){
    appComponent = component;
}

}

在我的 Robolectric/PowerMock 测试仪中:

@Before
public void before() throws Exception {

    App appMocked = PowerMockito.mock(App.class);
    App.setAppComponent(DaggerAppComponent.builder().appModule(new AppModule(appMocked)).build());
    ....
}

然后我的activity就叫了App.getAppComponent().inject(this);

仅供参考,我尽量不嘲笑应用程序 class 并使用了 ((App)RuntimeEnvironment.application),但这没有用。我还尝试将其子化 class,并在 Robolectric 的应用程序配置中使用它,但最终遇到了转换问题。所以我希望这能有所帮助。

当然,setter 不应投入生产。但这是我认为这可行的唯一方法。