【问题标题】:Android espresso - how to use dagger2 to inject dependenciesAndroid espresso - 如何使用 dagger2 注入依赖项
【发布时间】:2017-06-12 10:50:23
【问题描述】:

使用 dagger2 将依赖项注入 espresso 测试是我想做的。

我想要一种能够使用 dagger 为我的测试用例提供依赖项的方法。

特别是我想用匕首注入一个MockwebServer 类。这是怎么做到的? 我的项目已经设置了匕首。它现在是一个组件,单个组件有 5 个模块 看起来像这样:

@Singleton
@Component(modules = {AppModule.class, NetworkModule.class, RepositoryModule.class, UseCaseModule.class, ActivityModule.class, PresenterModule.class})
public interface AppComponent {

    void inject(NetworkSessionManager target);
    void inject(SplashActivity target);
    void inject(AuthenticationActivity target);
    void inject(WelcomeActivity target);
    void inject(LoginFragment target);
}

它运行良好。但是现在当我移动到 androidTest 文件夹进行 espresso 测试时,我将如何使用以下组件:

    //note the NetworkTestModule.class i want to use is defined instead of //networkModule.class
        @Singleton
        @Component(modules = {AppModule.class, NetworkTestModule.class, RepositoryModule.class, UseCaseModule.class, ActivityModule.class, PresenterModule.class})
        public interface AppTestComponent

 {

        void inject(NetworkSessionManager target);
        void inject(SplashActivity target);
        void inject(AuthenticationActivity target);
        void inject(WelcomeActivity target);
        void inject(LoginFragment target);
        void inject (MYTESTCLASS target);
    }

我一直在做什么将 AppTestComponent 保留在主源代码中,但它不能以这种方式看到 MYTESTCLASS?

我想注入我的类的原因是,我想在将 mockWebServer 类传递给改造后像这样注入一个 baseurl:

TestNetworkModule.java:

@Provides
@Singleton
public Retrofit provideRetrofit(Converter.Factory converter, OkHttpClient client, @Named(BASE_URL) String baseUrl, MockWebServer server) {
    return new Retrofit.Builder()
            .baseUrl(server.url("/").toString())
            .client(client)
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(converter)
            .build();
}

    @Singleton
    @Provides
    MockWebServer providerMockWebServer() {
        return new MockWebServer();
    }
    //....
    }

这样我可以获得 MockWebServer 的参考并在我的测试中使用它并对其进行改造工作,以便我可以进行快速集成测试

我也在 gradle 中使用以下依赖项,请确认:

 compile 'com.google.dagger:dagger:2.9'
testCompile 'com.google.dagger:dagger:2.9'
annotationProcessor 'com.google.dagger:dagger-compiler:2.9'

【问题讨论】:

    标签: android dependency-injection android-espresso dagger-2 mockwebserver


    【解决方案1】:

    我将尝试解释它是如何做到的:

    在您的应用程序类中,您应该指定包含您的 API 服务的应用程序组件:

    protected AppComponent initializeAppComponent() {
        return DaggerAppComponent.builder()
                .apiServiceModule(new APIServiceModule(this))
                .otherModules(new otherModules(this))
                .build();
    }
    

    然后像这样注入:

    @Override
    public void onCreate() {
        applicationComponent = initializeAppComponent();
        applicationComponent.inject(this)}};
    

    这是标准初始化。您只需将组件构建器移动到以后可以覆盖的方法。

    在您的 android 测试包中:

    现在,您需要创建新的应用程序类,它扩展了您的应用程序类,您可以在其中初始化匕首组件。

    所以现在您可以覆盖initializeAppComponent() 方法并通过扩展先前模块的新方法切换您的APIServiceModule。 它应该是这样的:

    public class MockApp extends App {
    
    @Override
    protected AppComponent initializeAppComponent() {
        return DaggerAppComponent.builder()
                .apiServiceModule(new MockAPIServiceModule(this))
                .otherModules(new OtherModules(this))
                .build();
    }
    
    @Module
    private class MockAPIServiceModule extends APIServiceModule {
    
        @Override
        public ApiService provideApiService(@Nonnull final Retrofit retrofit,
                                            @Nonnull final Gson gson) {
            return new ApiService() {
                @Override
                public Observable<LoginResponse> login(@Body final LoginRequest loginRequest) {
                    return // what you want to
                }
            }
        }
    }}
    

    您需要声明应该使用哪个Application 类进行测试。 现在你需要做两件事: 1.创建指向新App Class的新跑步者

    public class MockTestRunner extends AndroidJUnitRunner{
    
    @Override
    public void onCreate(Bundle arguments) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().build());
        super.onCreate(arguments);
    }
    @Override
    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        return super.newApplication(cl, MockApp.class.getName(), context);
    }}
    
    1. build.gradle中声明将使用哪个跑步者。

    testInstrumentationRunner ".MockTestRunner"

    就是这样。现在您的请求将使用模拟响应! 如果您有任何问题,请尽管提问。

    干杯

    【讨论】:

    • 这很好。我也通过为 dagger 创建一个重复的测试组件并将该测试组件与 dagger mock 一起使用来实现它。你的更好
    • 谢谢,很高兴听到这个消息 :)
    猜你喜欢
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多