简体   繁体   English

使用Dagger和Robolectric进行测试应用

[英]Using Dagger and Robolectric with test application

I am using MVP pattern with a Fragment( GalleryFragment ), where Application class( MainApplication ) sources MainActivityRepository and GalleryFragmentPresenter (grouped as DIModules ) which are provided to Fragment through field injection. 我正在使用带有Fragment( GalleryFragment )的MVP模式,其中Application类( MainApplication )通过字段注入提供给Fragment的MainActivityRepositoryGalleryFragmentPresenter (分组为DIModules )。

To test GalleryFragment in isolation, my idea was to use Robolectric configuration(@Config) to replace MainApplication entirely with a custom TestApplication sourcing mockDIModules . 为了测试GalleryFragment孤立,我的想法是使用Robolectric配置(@Config)取代MainApplication与定制完全TestApplication采购mockDIModules

GalleryFragmentTest runs until startFragment(galleryFragment) but I get a NullPointerException at MainApplication.getComponent().inject(this); GalleryFragmentTest一直运行到startFragment(galleryFragment)但我在MainApplication.getComponent().inject(this);得到一个NullPointerException MainApplication.getComponent().inject(this); inside GalleryFragment . GalleryFragment

I suspect this is because this line specifically uses MainApplication while everything else is dealt with TestApplication set by Robolectric @Config, but I'm not sure and I am looking for advice on how to successfully run tests using this custom TestApplication . 我怀疑这是因为这一行专门使用MainApplication而其他所有内容都由Robolectric TestApplication设置的TestApplication处理,但我不确定,我正在寻找有关如何使用此自定义TestApplication成功运行测试的TestApplication

While searching for possible solutions, I found out about using AndroidInjector from Dagger support library, which will get rid of MainApplication.getComponent().inject(this); 在搜索可能的解决方案时,我发现了使用Dagger支持库中的MainApplication.getComponent().inject(this); ,它将摆脱MainApplication.getComponent().inject(this); entirely but would this work? 完全但这会有用吗? https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3 https://android.jlelse.eu/android-and-dagger-2-10-androidinjector-5e9c523679a3

GalleryFragment.java 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 DIModules.java

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

AppComponent.java AppComponent.java

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

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

I am using dagger , dagger-android-support , dagger-compiler version 2.14.1 and robolectric:3.6.1 我使用的是daggerdagger-android-supportdagger-compiler版本2.14.1和robolectric:3.6.1

Of course, it is null . 当然,它是null Your fragment still tries to work with production application while you're doing things in the test application. 当您在测试应用程序中执行操作时,您的片段仍会尝试使用生产应用程序。

Change your injection code to next: 将注射代码更改为下一个:

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

And also make the method in your Application getComponent() as not static, so test app overrides it. 并且还将您的Application getComponent()方法设置为非静态,因此测试应用程序会覆盖它。

Another option is to change your TestApplication to next: 另一种选择是将TestApplication更改为下一个:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM