I am developing android app and I have implemented mockito in my viewmodel class in android but when I run the test I am getting following exceptions
org.mockito.exceptions.misusing.InjectMocksException:
Cannot instantiate @InjectMocks field named 'viewModel' of type 'class com.example.digiandroidapp.viewmodel.CarViewModel'.
You haven't provided the instance at field declaration so I tried to construct the instance.
However the constructor or the initialization block threw an exception : Parameter specified as non-null is null: method com.example.digiandroidapp.viewmodel.CarViewModel.<init>, parameter carsInfoDao
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:61)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: java.lang.NullPointerException: Parameter specified as non-null is null: method com.example.digiandroidapp.viewmodel.CarViewModel.<init>, parameter carsInfoDao
at com.example.digiandroidapp.viewmodel.CarViewModel.<init>(CarViewModel.kt)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at org.mockito.internal.util.reflection.ReflectionMemberAccessor.lambda$newInstance$0(ReflectionMemberAccessor.java:29)
at org.mockito.internal.util.reflection.ReflectionMemberAccessor.newInstance(ReflectionMemberAccessor.java:29)
at org.mockito.internal.util.reflection.ReflectionMemberAccessor.newInstance(ReflectionMemberAccessor.java:20)
at org.mockito.internal.util.reflection.FieldInitializer$ParameterizedConstructorInstantiator.instantiate(FieldInitializer.java:287)
at org.mockito.internal.util.reflection.FieldInitializer.acquireFieldInstance(FieldInitializer.java:146)
at org.mockito.internal.util.reflection.FieldInitializer.initialize(FieldInitializer.java:91)
at org.mockito.internal.configuration.injection.ConstructorInjection.processInjection(ConstructorInjection.java:48)
at org.mockito.internal.configuration.injection.MockInjectionStrategy.process(MockInjectionStrategy.java:68)
at org.mockito.internal.configuration.injection.MockInjectionStrategy.relayProcessToNextStrategy(MockInjectionStrategy.java:91)
at org.mockito.internal.configuration.injection.MockInjectionStrategy.process(MockInjectionStrategy.java:71)
at org.mockito.internal.configuration.injection.MockInjection$OngoingMockInjection.apply(MockInjection.java:88)
at org.mockito.internal.configuration.DefaultInjectionEngine.injectMocksOnFields(DefaultInjectionEngine.java:26)
at org.mockito.internal.configuration.InjectingAnnotationEngine.injectCloseableMocks(InjectingAnnotationEngine.java:119)
at org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks(InjectingAnnotationEngine.java:62)
at org.mockito.internal.configuration.InjectingAnnotationEngine.process(InjectingAnnotationEngine.java:49)
at org.mockito.MockitoAnnotations.openMocks(MockitoAnnotations.java:82)
at org.mockito.internal.framework.DefaultMockitoSession.<init>(DefaultMockitoSession.java:43)
at org.mockito.internal.session.DefaultMockitoSessionBuilder.startMocking(DefaultMockitoSessionBuilder.java:83)
at org.mockito.internal.junit.JUnitSessionStore$1.evaluate(JUnitSessionStore.java:38)
below my CarViewModel.kt
class CarViewModel(
private val api: ApiInterface,
private val carsInfoDao: CarsInfoDao,
private val carsLocationDao: CarsLocationDao,
) : ViewModel() {
private val _cars = MutableLiveData<List<CarInfo>>()
val cars: LiveData<List<CarInfo>> = _cars
private val _error = SingleLiveEvent<Exception>()
val error: LiveData<Exception> = _error
private val _loading = MutableLiveData<Boolean>()
val loading: LiveData<Boolean> = _loading
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
fun getAllCars() {
viewModelScope.launch {
try {
val result = api.getAllCars()
println("dataaaa -> $result")
_loading.value = true
_cars.value = result
val carsInfoList = mutableListOf<CarsInfoEntity>()
val carsLocationList = mutableListOf<CarsLocationEntity>()
result.forEach { carsInfo: CarInfo ->
carsInfoList.add(
CarsInfoEntity(
carsInfo.id,
carsInfo.brand,
carsInfo.model,
carsInfo.imageURL,
carsInfo.fuel,
carsInfo.pricePerDay,
carsInfo.currency,
carsInfo.year,
carsInfo.type,
carsInfo.status,
carsInfo.groupId,
carsInfo.registrationPlate,
carsInfo.createdAt,
carsInfo.updatedAt,
carsInfo.subjectTypeId
)
)
carsLocationList.add(
CarsLocationEntity(
carsInfo.id,
carsInfo.location.latitude,
carsInfo.location.longitude,
)
)
}
carsInfoDao.insertCarsInfo(carsInfoList)
carsLocationDao.insertCarsLocation(carsLocationList)
} catch (e: Exception) {
_error.value = e
} finally {
_loading.value = false
}
}
}
}
below ViewModelTest
class CarViewModelTest {
@get:Rule
val mockitoRule: MockitoRule = MockitoJUnit.rule()
@get:Rule
var mainCoroutineRule = MainCoroutineRule()
@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
@InjectMocks
private lateinit var viewModel: CarViewModel
@Mock
private lateinit var api: ApiInterface
@Mock
private lateinit var cars: List<CarInfo>
private val testDispatcher = TestCoroutineDispatcher()
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
}
@After
fun tearDown() {
Dispatchers.resetMain()
testDispatcher.cleanupTestCoroutines()
}
@Test
fun `get cars positive case`() {
val cardData = cars
observe(viewModel.cars)
wheneverBlocking { api.getAllCars() }.thenReturn(cardData)
viewModel.getAllCars()
assert(viewModel.cars.value == cardData)
}
@Test
fun `get cars negative case`() {
val userObserver = observe(viewModel.cars)
val errorObserver = observe(viewModel.error)
val exception = IOException("404")
wheneverBlocking { api.getAllCars() }.thenThrow(exception)
viewModel.getAllCars()
assert(viewModel.error.value == exception)
verifyZeroInteractions(userObserver)
verify(errorObserver).onChanged(exception)
}
}
I want to know what is causing an issue what I have to do in order to avoid exceptions I have followed many stackoverflow post it did not solve my issue
I fixed by adding MockitoAnnotations.initMocks(this) to setup method