使用Dagger和Robolectric进行测试应用

时间:2018-01-28 14:36:28

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

我正在使用带有片段(GalleryFragment)的MVP模式,其中Application类(MainApplication)来源MainActivityRepositoryGalleryFragmentPresenter(分组为DIModules)通过现场注射提供给Fragment。

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

GalleryFragmentTest一直运行到startFragment(galleryFragment)但我在MainApplication.getComponent().inject(this);内的GalleryFragment处遇到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);
    }
}

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

1 个答案:

答案 0 :(得分:0)

当然,它是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();
    }
}