使用Dagger和Robolectric进行测试应用程序

4

我正在使用 MVP 模式与一个 Fragment(GalleryFragment),应用程序类(MainApplication)提供 MainActivityRepositoryGalleryFragmentPresenter(作为 DIModules 分组),通过字段注入提供给 Fragment。

为了隔离地测试 GalleryFragment,我的想法是使用 Robolectric 配置 (@Config) 用自定义的 TestApplication 替换整个 MainApplication 并提供 mockDIModules

GalleryFragmentTest 正常运行到 startFragment(galleryFragment),但是在 GalleryFragment 中的 MainApplication.getComponent().inject(this); 处发生 NullPointerException。

我怀疑这是因为这一行具体使用了 MainApplication,而其他所有东西都被 Robolectric @Config 设置的 TestApplication 处理,但我不确定,并且正在寻求关于如何成功使用此自定义 TestApplication 运行测试的建议。

在寻找可能的解决方案时,我发现可以使用来自Dagger支持库的AndroidInjector来完全摆脱MainApplication.getComponent().inject(this);,但这是否有效呢? https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3

GalleryFragment.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();
    }
}

AppComponent.java

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

MainApplication.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();
    }
}

TestApplication.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);
    }
}

我正在使用版本为2.14.1的daggerdagger-android-supportdagger-compilerrobolectric:3.6.1

1个回答

1
当然,它是null。在您进行测试应用程序的操作时,您的片段仍然尝试与生产应用程序一起工作。
将您的注入代码更改为以下内容:
((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();
    }
}

我在做了一些更改后遇到了ClassCastException,但是扩展MainApplication解决了这个问题。感谢您的帮助 :) - Kei

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