android - 在测试应用程序中使用 Dagger 和 Robolectric

标签 android dependency-injection dagger-2 robolectric android-mvp

我将 MVP 模式与 fragment (GalleryFragment) 结合使用,其中应用程序类 (MainApplication) 来源 MainActivityRepositoryGalleryFragmentPresenter(分组为 DIModules),通过字段注入(inject)提供给 Fragment。

要单独测试 GalleryFragment,我的想法是使用 Robolectric 配置 (@Config) 将 MainApplication 完全替换为自定义 TestApplication 来源mockDIModules.

GalleryFragmentTest 一直运行到 startFragment(galleryFragment) 但我在 MainApplication.getComponent().inject(this); 处收到 NullPointerException GalleryFragment.

我怀疑这是因为这一行专门使用 MainApplication 而其他所有内容都由 Robolectric @Config 设置的 TestApplication 处理,但我不确定,我正在寻找有关如何使用此自定义 TestApplication 成功运行测试的建议。

在寻找可能的解决方案时,我发现了有关使用 Dagger 支持库中的 AndroidInjector 的信息,这将完全摆脱 MainApplication.getComponent().inject(this); 但这行得通吗? https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3

画廊 fragment .java

public class GalleryFragment extends Fragment {
    @Inject
    public MainActivityRepository mRepository;
    @Inject
    public GalleryFragmentPresenter mGalleryFragmentPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainApplication.getComponent().inject(this);   //NullPointerException here
        mGalleryFragmentPresenter.initialize(mRepository, value);
    }
}

DIModules.java

@Module
public class DIModules {
    @Provides
    public GalleryFragmentPresenter provideGalleryFragmentPresenter(){
        return new GalleryFragmentPresenter();
    }
    @Provides
    @Singleton
    public MainActivityRepository provideMainActivityRepository(){
        return new MainActivityRepository();
    }
}

应用组件.java

@Singleton
@Component(modules = DIModules.class)
public interface AppComponent {
        void inject(GalleryFragment galleryFragment);
}

主应用程序.java

public class MainApplication extends Application {
    public static AppComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        Realm.init(this);
        component = buildComponent();
    }
    public static AppComponent getComponent() {
        return component;
    }
    protected AppComponent buildComponent(){
        return DaggerAppComponent
                .builder()
                .dIModules(new DIModules())
                .build();
    }
}

测试应用程序.java

public class TestApplication extends Application {
    public static AppComponent component;

    @Override
    public void onCreate() {
        super.onCreate();
        component = buildComponent();
    }
    public static AppComponent getComponent() {
        return component;
    }
    protected AppComponent buildComponent(){
        return DaggerAppComponent.builder()
                .dIModules(new mockDIModules())
                .build();
    }
}

GalleryFragmentTest.java

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class,
        application = TestApplication.class)
public class GalleryFragmentTest {
    @Test
    public void allItemTabTest() throws Exception {
        GalleryFragment galleryFragment = GalleryFragment.newInstance(value);
        startFragment(galleryFragment);
        assertNotNull(galleryFragment);
    }
}

我正在使用 daggerdagger-android-supportdagger-compiler 版本 2.14.1 和 robolectric:3.6。 1

最佳答案

当然是null。当您在测试应用程序中执行操作时,您的 fragment 仍会尝试使用生产应用程序。

将您的注入(inject)代码更改为下一步:

((MainApplication) getContext().getApplicationContext()).getComponent().inject(this);

并且还使您的应用程序 getComponent() 中的方法不是静态的,因此测试应用程序会覆盖它。

另一种选择是将您的 TestApplication 更改为下一个:

public class TestApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        buildComponent();
    }

    private void buildComponent(){
        Application.component = DaggerAppComponent.builder()
                .dIModules(new mockDIModules())
                .build();
    }
}

关于android - 在测试应用程序中使用 Dagger 和 Robolectric,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48487475/

相关文章:

带有类型丰富的 Scala 测试

android - 子组件(无作用域)可能不引用作用域绑定(bind) : @Singleton @Provides @org. jetbrains.annotations.NotNull

android - 为什么我应该为 View 模型使用 viewmodelproviders?

java - 覆盖默认的 Android 主题

java - 模糊下面的图层

android - 我们应该走电晕之路吗?

android - 将现有的 cordova cli 项目从 3.3.1 升级到 3.5

c# - 如何配置 Autofac 以解析 CQRS 处理程序并在 Web API 项目中编写其查询调度程序

java - 动态注入(inject) map

java - 在 Android 应用程序中放置数据库连接的位置