Testing Flow with MVVM result NullPointerException

Viewed 358

I am trying to test the return value of a ViewModel method. When the method is called, a usecase is executed and return a flow. Then the method return a liveData from the flow:

The viewmodel:

class HomeDataViewModel
@Inject constructor(private val getMyObjectUseCase: GetMyObjectUseCase) : ViewModel() {

fun fetchData() =
    getMyObjectUseCase.execute()
        .onStart { emit(ResultOf.InProgress) }
        .asLiveData()
 }

The Usecase:

class GetMyObjectUseCase
@Inject constructor(private val repository: DataRepository) {
    fun execute(): Flow<ResultOf<MyObject>> = flow {
        emit(ResultOf.Success(MyObject("data1", "data2", listOf())))
    }
}

The test:

@RunWith(MockitoJUnitRunner::class)
class HomeDataViewModelTest {
    @get:Rule
    val instantExecutorRule = InstantTaskExecutorRule()

    @get:Rule
    val testCoroutineRule = TestCoroutineRule()

    @Mock
    private lateinit var mockObserver: Observer<ResultOf<MyObject>>

    //Class under test
    private lateinit var sut: HomeDataViewModel

    @Mock
    lateinit var useCase: GetMyObjectUseCase

    @Captor
    private lateinit var captor: ArgumentCaptor<ResultOf<MyObject>>


    @Before
    fun setup() {
        sut = HomeDataViewModel(useCase)
    }

    @Test
    fun `is live data emitting`() = testCoroutineRule.runBlockingTest {
        val objectReturn1 = ResultOf.InProgress
        val flow = flow { emit(objectReturn1) }
        Mockito.`when`(useCase.execute()).thenReturn(flow)

        val livedata = sut.fetchData()
        livedata.observeForever(mockObserver)
        Mockito.verify(mockObserver).onChanged(captor.capture())

        assertEquals(objectReturn1, captor.value)
    }
}

The test past (is green) but it throws an exception:

Exception in thread "main" java.lang.NullPointerException
    at kotlinx.coroutines.flow.FlowKt__EmittersKt$onStart$$inlined$unsafeFlow$1.collect(SafeCollector.common.kt:120)
    at androidx.lifecycle.FlowLiveDataConversions$asLiveData$1.invokeSuspend(FlowLiveData.kt:149)
    at androidx.lifecycle.FlowLiveDataConversions$asLiveData$1.invoke(FlowLiveData.kt)
    at androidx.lifecycle.BlockRunner$maybeRun$1.invokeSuspend(CoroutineLiveData.kt:176)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)

What am I doing wrong?

0 Answers
Related