4

使用 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 之后注入它,如下所示:

测试网络模块.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'
4

1 回答 1

11

我将尝试解释如何做到这一点:

在您的应用程序类中,您应该指定包含您的 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 测试包中:

现在,您需要创建新的 Application 类来扩展您的应用程序类,您可以在其中初始化 dagger 组件。

因此,现在您可以覆盖方法并通过扩展先前模块的新方法来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"

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

干杯

于 2017-06-19T13:55:44.130 回答