I am having trouble creating a test class. Basically I want to test my view model class which performs network call. The class network component is injected by using dagger needs the context parameter to check connection, this is my view model:
class MyViewModel(application: Application): AndroidViewModel(application) {
@Inject lateinit var network: NetworkService
init {
DaggerNetworkComponent.builder().networkModule(NetworkModule(application.applicationContext))
.build().inject(this)
network.callNetwork()
}
}
And the test class is something like
lateinit var myViewModel: MyViewModel
@Test
fun testMyNetwork() {
application = Mockito.mock(Application::class.java)
myViewModel = MyViewModel(application)
}
The application.applicationContext
always returns null which then returns IllegalStateException
Is there any solution for this?
I think there are two possibilities here. I used 2nd one and know it works, 1st one is my guess.
(1)
You are mocking Application. Then you are trying to use its applicationContext
however you did not mock it. You need to mock it as well:
val context = Mockito.mock(Context::class.java)
Mockito.`when`(application.applicationContext).thenReturn(context)
(2)
Assume 1) your test is instrumentation test 2) you are using subclass of Application
- say, MyApplication
.
You will then have to create its subclass - say, TestMyApplication
. Next step would be to create subclass of AndroidJUnitRunner
, may be like this:
public class MyInstrumentationTestRunner extends AndroidJUnitRunner {
@Override
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return Instrumentation.newApplication(TestMyApplication.class, context);
}
}
Finally, you need to tell android to use this runner:
allprojects {
ext {
....
testInstrumentationRunner = "com...MyInstrumentationTestRunner"
}
}
As a result of the above, application context will be instance of TestMyApplication across your instrumentation tests.