Search code examples
androidkotlinandroid-espressodagger-2dagger

(DAGGER-ANDROID) Can not use @Inject on an Espresso Test and can not use mockWebServer


I'm trying to create Espresso tests and using a mockWebServer the thing is when I try to create my mockWebServer it calls the real api call and I want to intercept it and mock the response.

My dagger organisation is :

My App

open class App : Application(), HasAndroidInjector {

    lateinit var application: Application

    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Any>

    override fun androidInjector(): AndroidInjector<Any> = androidInjector

    override fun onCreate() {
        super.onCreate()
        DaggerAppComponent.factory()
            .create(this)
            .inject(this)
        this.application = this
    }
}

Then MyAppComponent

@Singleton
@Component(
    modules = [
        AndroidInjectionModule::class,
        AppModule::class,
        RetrofitModule::class,
        RoomModule::class,
        AppFeaturesModule::class
    ]
)
interface AppComponent : AndroidInjector<App> {

    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: App): AppComponent
    }
}

Then I've created this TestApp

class TestApp : App() {

    override fun androidInjector(): AndroidInjector<Any> = androidInjector

    override fun onCreate() {
        DaggerTestAppComponent.factory()
            .create(this)
            .inject(this)
    }
}

And this is my TestAppComponent

@Singleton
@Component(
    modules = [
        AndroidInjectionModule::class,
        AppModule::class,
        TestRetrofitModule::class,
        AppFeaturesModule::class,
        RoomModule::class]
)
interface TestAppComponent : AppComponent {
    @Component.Factory
    interface Factory {
        fun create(@BindsInstance application: App): TestAppComponent
    }
}

Note: Here I've created a new module, called TestRetrofitModule where the BASE_URL is "http://localhost:8080", I don't know if I need something else.

Also I've created the TestRunner

class TestRunner : AndroidJUnitRunner() {

    override fun newApplication(
        cl: ClassLoader?,
        className: String?,
        context: Context?
    ): Application {
        return super.newApplication(cl, TestApp::class.java.name, context)
    }

}

And put it on the testInstrumentationRunner

Problem 1

I can not use

@Inject
lateinit var okHttpClient: OkHttpClient

because it says that it's not initialised.

Problem 2 (Solved thanks Skizo)

My mockWebServer is not dispatching the responses even-though is not pointing the real api call, is pointing the one that I've put to the TestRetrofitModule, the thing is that I have to link that mockWebServer and Retrofit.


Solution

  • I had the same problem with mockWebServer recently, what you need to do is to put a breakpoint and see what's the error, in my case I put it on my BaseRepository where I was doing the call, and found that the exception was :

    java.net.UnknownServiceException: CLEARTEXT communication to localhost not permitted by network security policy
    

    What I did to solve the problem is add this on my manifest.xml

    android:usesCleartextTraffic="true"
    

    But you may have to use other approaches you can take a look on android-8-cleartext-http-traffic-not-permitted.