如何转换RuntimeEnvironment.application?(涉及IT技术)

3
运行Robolectric测试时,RuntimeEnvironment.application的类型由您的配置决定。例如,如果我将RoboApplication.class配置为我的测试应用程序,则我可以将RuntimeEnvironment.application强制转换为我的类型而不会失败。
RoboApplication app = (RoboApplication) RuntimeEnvironment.application;
app.doSomething();

然而,一旦我集成了PowerMock,类型转换出现错误:
java.lang.ClassCastException: RoboApplication cannot be cast to RoboApplication

我该如何解决这个问题?

你能在调试中看到完整的类名吗? - Eugen Martynov
可以的,它是RoboApplication,在配置中是相同类型的。 - Some Noob Student
2个回答

4
这是一个问题,因为 PowerMock 和 Robolectric 使用它们自己的类加载器相互不兼容
尽管名称相同,但 Class 对象实际上并不相同:Robolectric 和 PowerMock 都通过 自定义类加载器 加载测试。这些类加载器会更改相关的类,使您能够替换静态/最终 Android 系统类和方法 [Robolectric] 或所有静态/最终类 [PowerMock]。这是 PowerMock 和 Robolectric 都依赖于有自己的 JUnit4 Runner 的部分原因:这样他们就可以从自己修改的类加载器中加载适当的类。
因此,即使它们具有相同的名称并且 源文件是相同的,也不能将实例强制转换为彼此的类:每个框架都可以更改类实现,因此它们不一定与彼此兼容。
您需要选择其中一个框架:使用Robolectric 遮罩,可能直接使用 EasyMock 或 Mockito,或者使用 PowerMock 自己手动停用 Android 基础架构调用。
另请参见:
- 在尝试将其强制转换为相同类时出现ClassCastException - 跨类加载器转换?

非常感谢您的精彩写作! - Some Noob Student

1

我还需要一个应用程序引用来启动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());
    ....
}

然后我的活动只需调用App.getAppComponent().inject(this);

顺便说一下,我试着不嘲笑应用程序类并使用((App)RuntimeEnvironment.application),但那行不通。我还尝试过子类化它,并在Robolectric的应用程序配置中使用它,但最终遇到了强制转换问题。所以我希望这能有所帮助。

当然,这个setter不应该用于生产环境。但这是我能想到的唯一方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接