Injecting dependencies into espresso test using dagger2 is what i would like to do.
I would like a way to be able to provide dependencies for my test cases using dagger.
In particular there is a MockwebServer class i want to inject with dagger. How is this done? My project already has dagger set up. its a single component for now and the single componeent has 5 modules which look like this:
@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);
}
AND IT WORKS FINE. But now when i move to the androidTest folder to do an espresso test how would i use the following component:
//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);
}
what i have been doing it keeping the AppTestComponent in the main source code but it cant see MYTESTCLASS this way ?
The reason i want to inject into my class, is that i want to inject a mockWebServer class after passing it to retrofit as the baseurl like this:
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();
}
//....
}
this way i can get a reference of the MockWebServer and use it in my tests and have retrofit work with it so i can do fast integration tests
also in gradle i am using the following dependencies please confirm:
compile 'com.google.dagger:dagger:2.9'
testCompile 'com.google.dagger:dagger:2.9'
annotationProcessor 'com.google.dagger:dagger-compiler:2.9'
I will try to explain how do it:
In your application class you should have specified Application component which contains your API service:
protected AppComponent initializeAppComponent() {
return DaggerAppComponent.builder()
.apiServiceModule(new APIServiceModule(this))
.otherModules(new otherModules(this))
.build();
}
And inject like this:
@Override
public void onCreate() {
applicationComponent = initializeAppComponent();
applicationComponent.inject(this)}};
It is standard initialization. You need to just move component builder to method which can be overrided later.
In your android Tests package:
Now, you need to create new Application class which extends your application class where you have your dagger component initialization.
So now you can override initializeAppComponent()
method and switch your APIServiceModule
by the new one which extends previous Module.
It should looks like this:
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
}
}
}
}}
You need to declare which Application
class should be used for tests.
Now you need to do 2 more things:
1. Create new runner which pointing on new 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);
}}
build.gradle
.testInstrumentationRunner ".MockTestRunner"
Thats it. Now your requests will use mocked responses! If you have any question just ask.
Cheers
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With