首页 > 解决方案 > Kotlin Coroutines ViewModel Unit Testing with Mockito using Retrofit MVVM throws Null pointer Exception

问题描述


我尝试对使用 Kotlin 协程进行改造 API 调用的 ViewModel 进行单元测试。单元测试失败,出现空指针异常。
当使用 Retrofit RXJAva UnitTest Passes 进行相同尝试时。使用 Mockito 框架。
请检查我的代码并让我知道我的代码中出现的错误。
请在下面找到 ViewModel 和 UnitTest 类文件:
fetchResponseFromAPI()方法进行 API 调用以获取数据
RetroCoroutineViewModel.kt

 class RetroCoroutineViewModel  : ViewModel(),LifecycleObserver{

private val errorOnAPI = MutableLiveData<String>()
private val mutableLiveData:MutableLiveData<List<RetroRxModel>> = MutableLiveData()
var loading : MutableLiveData<Boolean> = MutableLiveData()

@Inject
lateinit var retrofit: Retrofit
lateinit var apiService: APIService

init {
    DaggerRetroRxComponent.create().inject(this)
    loading.value = true
    apiService = retrofit.create(APIService::class.java)
}



 val postsMutableLiveData:MutableLiveData<List<RetroRxModel>> = MutableLiveData()

**@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun fetchResponseFromAPI(){**
    viewModelScope.launch {

        try{

            val response  = apiService.fetchUserPosts()
            if(response.isSuccessful){
                postsMutableLiveData.postValue(response.body())
                loading.value = false
            }else{
                loading.value = false
                errorOnAPI.postValue("Something went wrong::${response.message()}")
            }



        }catch (e:Exception){
            loading.value = false
            errorOnAPI.postValue("Something went wrong::${e.localizedMessage}")
        }

    }

}

fun fetchPostLiveData(): LiveData<List<RetroRxModel>>  = postsMutableLiveData


override fun onCleared() {
    super.onCleared()

}


fun fetchError(): LiveData<String> = errorOnAPI



fun fetchLoadStatus():LiveData<Boolean> = loading

    private  fun onError(message: String){
       errorOnAPI.value = message
       loading.value = false


     }
     }

RetroCoroutineViewModelTest:

@RunWith(MockitoJUnitRunner::class)
@ExperimentalCoroutinesApi
   class RetroCoroutineViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()

@get:Rule
val testCoroutineRule = TestCoroutineRule()

@Mock
lateinit var retrofit: Retrofit

@Mock
lateinit var apiService: APIService

lateinit var retroCoroutineViewModel: RetroCoroutineViewModel

private lateinit var response: Response<List<RetroRxModel>>

private  var loading: Boolean = false

      @Before
     fun setUp(){
       MockitoAnnotations.initMocks(this)

      } 



       @Test
       fun fetchRetroInfoTest_success(){
       retroCoroutineViewModel = RetroCoroutineViewModel()
        testCoroutineRule.runBlockingTest {
        var retroRxModel = RetroRxModel("tile", "body", "1")
        var retroRXModelList = ArrayList<RetroRxModel>()
        retroRXModelList.add(retroRxModel)
        response = Response.success(retroRXModelList)
        if (retrofit != null) {

            if (apiService != null) {
                Mockito.`when`(apiService.fetchUserPosts()).thenReturn(response)
                retroCoroutineViewModel.fetchResponseFromAPI()

            }
        }
        val funResponse = retroCoroutineViewModel.fetchPostLiveData()
        println("Response::::${funResponse.value}")

         Assert.assertEquals(1,funResponse.value?.size)
        Assert.assertEquals(loading,retroCoroutineViewModel.loading)



    }
}

}


当我尝试运行单元测试用例时,我观察到以下异常:

java.lang.AssertionError:预期:1 实际:null

at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:118)
at org.junit.Assert.assertEquals(Assert.java:144)
at com.rxretrofit.RetroCoroutineViewModelTest$fetchRetroInfoTest_success$1.invokeSuspend(RetroCoroutineViewModelTest.kt:75)

构建.Gradle:

    testImplementation "org.mockito:mockito-core:3.3.3"   
    testImplementation 'androidx.arch.core:core-testing:2.1.0'
    testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.3.4'

标签: androidkotlinkotlin-coroutinesandroid-mvvmmockito-kotlin

解决方案


推荐阅读