NullPointerException при запуске теста JUnit4 с MockitoHint «Не используется ...» и «args ok?» - PullRequest
0 голосов
/ 07 августа 2020

Я пытаюсь запустить этот тест JUnit 4 для проверки правильности LiveData значений объекта с именем dbState:

    @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$1.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()
                }
            )
    }

Я новичок в модульном тестировании, и меня это совершенно сбивает с толку, особенно с тех пор, как я прошел аналогичный тест. Это тестирует другой объект LiveData с именем uiState

    @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)
}

1 Ответ

0 голосов
/ 10 августа 2020

Решил, сначала изменив мой тест на использование any, что привело к сообщению об ошибке any(GithubUser::class.java) must not be null. Затем я нашел это сообщение SO , используя следующую функцию:

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

Итак, я добавил предыдущую функцию в свой тестовый класс и изменил свой тест, чтобы он выглядел так:

    @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))
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...