androidkotlin-coroutineskoinandroid-unit-testing

Unit test fails for coroutine if "by inject{parametersOf("someValue")}" is present within coroutine


I have a coroutine in my viewModel which runs perfectly fine. When I try to unit test the same, it throws the following error "Could not create instance for [type:Factory,primary_type:..MyService"

I am injecting a service and making an API call which works fine while unit testing. If the API fails, I am retrying the same API call with a new instance of Service with different parameters. This works fine in my application but fails in unit test. Here is the following code:

coroutineScope.launch {
        try {
            var getResponse = myApi?.getCodeApi()
            if (getResponse?.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
                // Retrying with instance of service with a different token
                val newMyApiService: MyService? by inject { parametersOf(newToken) }
                getResponse = newMyApiService?.getCodeApi()

            }
            checkResponse(getResponse)
        } catch (exception: Exception) {
            Timber.e(exception)
        }
    }

Is there a way to fix this?. I have taken all the required measures like startingKoinApp for the test environment, also included the required Koin modules before starting to test.

A part of unit test looks something like this

 whenever(myAPi.getCodeApi()).thenReturn(properResponse)
        val errorResponse : Response<DataModel> = mock()
        whenever(response.code()).thenReturn(HttpsURLConnection.HTTP_UNAUTHORIZED)
        whenever(myAPi.getCodeApi()).thenReturn(errorResponse)

Solution

  • This can be fixed by replacing the line

    val newMyApiService: MyService? by inject { parametersOf(newToken) }
    

    with

    val newMyApiService: getNewService(newToken)
    

    The new method will be

    fun getNewService(newToken: String): MyService? {
      return MyService? by inject { parametersOf(newToken) }
    }
    

    Now within your unit test, you can mock the method using power mockito

    val underTestsSpy = PowerMockito.spy(underTests)
            PowerMockito.doReturn(myserviceApi).`when`(underTestsSpy, 
     "getNewService", newToken)
    

    Through this, you can mock a new service instance that is created within the method being tested