AndroidInjector和Espresso

时间:2017-05-02 02:13:29

标签: android-espresso dagger-2

使用AndroidInjector和Subcomponents使得无法将对象范围内的活动注入到Espresso的Test类中。

以前使用应用程序级组件和活动组件,只要您创建继承活动组件的测试组件,就可以为非活动的测试类调用inject()。

示例:

活动组件

@ActivityScope
@Component(
    dependencies = ApplicationComponent.class,
    modules = {
            NowPlayingActivityModule.class
    })
public interface NowPlayingActivityComponent {
    void inject(NowPlayingActivity activity);
}

测试类组件

@ActivityScope
@Component(
    dependencies = TestApplicationComponent.class,
    modules = {
            TestNowPlayingActivityModule.class,
            ActivityModule.class
    })
 public interface TestNowPlayingActivityComponent extends NowPlayingActivityComponent {
    void inject(NowPlayingActivityTest nowPlayingActivityTest);
}

测试模块

@Module
public class TestNowPlayingActivityModule {
    private NowPlayingActivityModule nowPlayingActivityModule;

    public TestNowPlayingActivityModule(NowPlayingActivityModule nowPlayingActivityModule) {
        this.nowPlayingActivityModule = nowPlayingActivityModule;
    }

    @Provides
    @ActivityScope
    public ServiceGateway providesServiceGateway(ServiceApi serviceApi) {
        return nowPlayingActivityModule.providesServiceGateway(serviceApi);
    }

    @Provides
    @ActivityScope
    public NowPlayingPresenter providesNowPlayingPresenter(NowPlayingInteractor nowPlayingInteractor) {
        //In order to make sure espresso idles the view checks, we put the IdlingResource on the presenter.
        return Mockito.spy(new NowPlayingPresenterImpl_IdlingResource(nowPlayingActivityModule.getNowPlayingViewModel(),
            nowPlayingInteractor));
    }
}

在测试类中

TestNowPlayingActivityComponent mockNowPlayingActivityComponent = DaggerTestNowPlayingActivityComponent.builder()
            .testApplicationComponent((TestApplicationComponent) mvpExampleApplication.getComponent())
            .testNowPlayingActivityModule(new TestNowPlayingActivityModule(nowPlayingActivityModule))
            .build();

mockNowPlayingActivityComponent.inject((NowPlayingActivity) activity);
mockNowPlayingActivityComponent.inject(NowPlayingActivityTest.this);

人们如何访问自动生成的活动模块并在espresso UI Test中使用它们?我希望能够访问像“ServiceGateway”这样的对象。上面的“NowPlayingPresenter”并在测试中使用它们。模拟,间谍或空闲资源。上面示例中的空闲资源是“NowPlayingPresenter”具体实现,我在每次单独测试时都会传递给espresso。

2 个答案:

答案 0 :(得分:0)

前几天我设法使用自定义测试运行器进行了一些hacky方法来解决这个问题。首先是拥有TestRunner for faking the Android Application。现在,您可以简单地扩展主app类并覆盖onCreate(),注入一个component built especially for testing,返回模拟实例而不是真实实例。

答案 1 :(得分:0)

我发现自己处于类似情况。这是我的问题Espresso testing with Dagger 2 and custom scopes。使用Espresso进行测试时注入嘲笑非常棘手。

mcassiano建议的方法是解决这个问题的第一个想法。但是,我没有采用这种方法,因为必须创建代码开销。我很想知道mcassiano创建的Espresso测试是什么样的。我假设您为Activity注册了一个ActivityTestRule,以便注入模拟。

在使用Dagger 2的理想场景中,我想避免以下情况:

  • 拥有一个知道所有其他组件的应用程序组件
  • 让应用程序组件为整个应用程序提供所有依赖项

后者我认为是一种代码味道,因为如果我们最终遇到上述任何一种情况,我们将拥有一个巨大的App组件和模块,它们与每个应用程序功能紧密结合。

应该发生的是让每个功能都负责注入它自己的依赖项。

关于寻找注入模拟的解决方案,我有以下想法,我没有实现,因为我不想将测试与生产代码混合。但是,如果你们分享你的想法,我们将不胜感激。

  1. 介绍一个仅作为测试设置的一部分初始化的组件构建器,如果已初始化,则在活动代码中使用此设置,否则设置实际组件。
  2. 在每个要素模块中检查构建类型并提供模拟,如果构建类型= espresso否则为真实对象