android - 如何使用 Dagger2 将 Activity 范围内的依赖项替换为模拟

标签 android unit-testing dependency-injection dagger dagger-2

我的 Activity 中有一个作用域依赖项,我想用一些模拟来测试该 Activity。我已经阅读了不同的方法,建议在测试期间用测试组件替换应用程序组件,但我想要的是替换 Activity 组件。

例如,我想在我的 MVP 设置中针对模拟演示者测试 Activity。

我认为通过在 Activity 上调用 setComponent() 来替换组件是行不通的,因为 Activity 依赖项已经通过字段注入(inject)注入(inject),因此在测试期间,将使用真实对象。

我该如何解决这个问题? Dagger1 呢?是否有同样的问题?

最佳答案

注入(inject)组件

首先,您创建一个静态类作为您的 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();
    }
}

然后只需在您的 Activity 中执行 ActivityComponentFactory.getInstance().createActivityComponent().inject(this);

为了测试,您可以在创建 Activity 之前替换方法中的工厂。

提供模拟

正如@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 代码生成将会失败。

这是可行的,因为模块只是简单的工厂——生成的组件类负责缓存作用域实例的实例。 @Scope 注释由代码生成器使用,但在运行时无关紧要。

关于android - 如何使用 Dagger2 将 Activity 范围内的依赖项替换为模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32281503/

相关文章:

android - 仅在Android上查询时出现SQL逻辑错误

unit-testing - react 堆项目 : wait while broadcaster finish

java - SpringBoot : Unsatisfied dependency NoSuchBeanDefinitionException, 期望至少有 1 个有资格作为 Autowiring 候选者的 bean

android - 如何在 Eclipse AVD 中使用 Android 手机边框获取屏幕截图?

android - 如何仅在选中复选框时才显示 toast 消息?

c# - 单元测试 WinForms

unit-testing - 使用 Mocha 进行参数化测试

c# - 这是 "Bastard injection anti-pattern"的一个很好的例子吗?

go - 嵌套依赖注入(inject)在 golang 中是否可以接受?

android - 如何使用 gson 在 json 现有结构中再插入一项?