运行 JUnit4 测试时出现 NullPointerException,使用 MockitoHint "Unused..." 和 "args ok?"

NullPointerException when running JUnit4 test, with MockitoHint "Unused..." and "args ok?"

我正在尝试 运行 此 JUnit 4 测试以检查名为 dbState:

的对象的正确 LiveData
    @Test
fun `saveNoteToDb - correct DB states`() {
    val dbStatus = SUT.dbState?.testObserver()
    val githubUser = GithubUser("", "")

    `when`(insertUserUseCase.insert(githubUser))
        .thenReturn(Completable.complete())

    SUT.saveNoteToDb("", "")

    Truth.assert_()
        .that(dbStatus?.observedValues)
        .isEqualTo(listOf(DB_SAVING, NOTE_SAVED))
}

但是我得到了一个 NullPointerException,Mockito 添加了一些不太有用的提示:

[MockitoHint] ProfileViewModelTest.saveNoteToDb - correct DB states (see javadoc for MockitoHint):
[MockitoHint] 1. Unused... -> at com.something.someapp.ui.profile.ProfileViewModelTest.saveNoteToDb - correct DB states(ProfileViewModelTest.kt:88)
[MockitoHint]  ...args ok? -> at com.something.someapp.ui.profile.ProfileViewModel.saveNoteToDb(ProfileViewModel.kt:54)


java.lang.NullPointerException
    at com.something.someapp.ui.profile.ProfileViewModel.saveNoteToDb(ProfileViewModel.kt:55)
    at com.something.someapp.ui.profile.ProfileViewModelTest.saveNoteToDb - correct DB states(ProfileViewModelTest.kt:91)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)

正在测试的函数如下所示:

    fun saveNoteToDb(userName: String, note: String) {
        compositeDisposable += insertUserUseCase.insert(GithubUser(userName, note))
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSubscribe { _dbState.value = DB_SAVING }
            .subscribeBy(
                onComplete = { _dbState.value = NOTE_SAVED },
                onError = {
                    _dbState.value = it.message?.let { msg -> DB_ERROR(msg) }
                    it.printStackTrace()
                }
            )
    }

我是单元测试的新手,对此我完全感到困惑,尤其是在我通过了一个类似的测试之后。这将测试另一个名为 uiState

LiveData 对象
    @Test
    fun `fetchUserDetails - correct UI states`() {
        val uiStatus = SUT.uiState?.testObserver()

        `when`(searchUserUseCase.searchForUser("username")).thenReturn(Single.just(
            SearchUserResponse()
        ))

        SUT.fetchUserDetails("username")

        Truth.assert_()
            .that(uiStatus?.observedValues)
            .isEqualTo(listOf(LOADING, SUCCESS))
    }

这里是之前测试成功的正在测试的函数:

    fun fetchUserDetails(userName: String) {
        compositeDisposable += searchUserUseCase.searchForUser(userName)
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .doOnSubscribe { _uiState.value = LOADING }
            .subscribeBy(
                onSuccess = {
                    followers.set(it.followers.toString())
                    following.set(it.following.toString())
                    name.set(it.name)
                    location.set(it.location)
                    _uiState.value = SUCCESS
                },
                onError = { error ->
                    error.printStackTrace()
                    _uiState.value = error.message?.let {
                        ERROR(it)
                    }
                }
            )
    }

testObserver是这样的,供参考:

open class TestObserver<T> : Observer<T> {

    val observedValues = mutableListOf<T?>()

    override fun onChanged(value: T?) {
        observedValues.add(value)
    }
}

fun <T> LiveData<T>.testObserver() = TestObserver<T>().also {
    observeForever(it)
}

通过首先将我的测试更改为使用 any 来解决它,这导致 any(GithubUser::class.java) must not be null 错误消息。然后我使用以下函数找到了这个 SO post

fun <T> any(): T = Mockito.any<T>()

所以我将之前的函数添加到我的测试中 class 并将我的测试更改为如下所示:

    @Test
    fun `saveNoteToDb - correct DB states`() {
        val dbStatus = SUT.dbState?.testObserver()

        `when`(insertUserUseCase.insert(any()))
            .thenReturn(Completable.complete())

        SUT.saveNoteToDb("", "")

        Truth.assert_()
            .that(dbStatus?.observedValues)
            .isEqualTo(listOf(DB_SAVING, NOTE_SAVED))
    }