我的Activity中有一个作用域依赖项,我想用一些模拟测试该活动.我已经阅读了有关在测试期间建议用测试组件替换Application组件的不同方法,但我想要的是替换Activity组件.
例如,我想在我的MVP设置中测试针对模拟演示者的Activity.
我相信通过调用Activity上的setComponent()替换组件将不起作用,因为Activity依赖已经通过字段注入注入,因此在测试期间,将使用真实对象.
我该如何解决这个问题? Dagger1怎么样?它有同样的问题吗?
最佳答案 注入组件
首先,创建一个静态类作为Activity的工厂.我看起来有点像这样:
public class ActivityComponentFactory {
private static ActivityComponentFactory sInstance;
public static ActivityComponentFactory getInstance() {
if(sInstance == null) sInstance = new ActivityComponentFactory();
return sInstance;
}
@VisibleForTesting
public static void setInstance(ActivityComponentFactory instance) {
sInstance = instance;
}
private ActivityComponentFactory() {
// Singleton
}
public ActivityComponent createActivityComponent() {
return DaggerActivityComponent.create();
}
}
然后只做ActivityComponentFactory.getInstance().createActivityComponent().inject(this);在你的活动中.
对于测试,您可以在创建活动之前替换方法中的工厂.
提供嘲笑
正如@ EpicPandaForce的答案所表明的那样,这样做的官方支持方式目前涉及大量的样板和复制/粘贴代码. Dagger 2团队需要提供一种更简单的部分覆盖模块的方法.
直到他们这样做,这是我的非正式方式:只需扩展模块.
假设您想用模拟替换ListViewPresenter.假设您有一个PresenterModule,如下所示:
@Module @ActivityScope
public class PresenterModule {
@ActivityScope
public ListViewPresenter provideListViewPresenter() {
return new ListViewPresenter();
}
@ActivityScope
public SomeOtherPresenter provideSomeOtherPresenter() {
return new SomeOtherPresenter();
}
}
您可以在测试设置中执行此操作:
ActivityComponentFactory.setInstance(new ActivityComponentFactory() {
@Override
public ActivityComponent createActivityComponent() {
return DaggerActivityComponent.builder()
.presenterModule(new PresenterModule() {
@Override
public ListViewPresenter provideListViewPresenter() {
// Note you don't have to use Mockito, it's just what I use
return Mockito.mock(ListViewPresenter.class);
}
})
.build();
}
});
……它只是有效!
请注意,您不必在@Override方法中包含@Provides批注.事实上,如果你这样做,Dagger 2代码生成将失败.
这是有效的,因为模块只是简单的工厂 – 生成的Component类负责缓存作用域实例的实例. @Scope注释由代码生成器使用,但在运行时无关紧要.