对LiveData Observer进行单元测试会导致Junit5出现NullPointer异常

问题描述 投票:1回答:1

我正在使用Android数据绑定来侦听实时数据更改,我想观察viewmodel级别的更改(而不是观察片段,然后将回调发送到viewmodel)observerForever很有趣,因为它对我有用。但是,当我运行测试时,出现以下错误:

java.lang.NullPointerException
at androidx.arch.core.executor.DefaultTaskExecutor.isMainThread(DefaultTaskExecutor.java:77)
at androidx.arch.core.executor.ArchTaskExecutor.isMainThread(ArchTaskExecutor.java:116)
at androidx.lifecycle.LiveData.assertMainThread(LiveData.java:461)
at androidx.lifecycle.LiveData.observeForever(LiveData.java:222)
at com.bcgdv.ber.maha.login.ui.LoginViewModel.<init>(LoginViewModel.kt:43)
at com.bcgdv.ber.maha.login.ui.LoginViewModelTest.<init>(LoginViewModelTest.kt:26)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:443)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:60)

我的代码在viewmodel类中如下:

val observerEmail: Observer<String> = Observer {
    setEmailError(it)
    checkLoginButton()
}
var email = MutableLiveData<String>()
init {
    email.observeForever(observerEmail)
}

还要注意,我正在使用Junit5。

android data-binding android-livedata observer-pattern
1个回答
0
投票

基本上,您需要摆脱测试中的isMainThread调用。

对于Junit 4,有一个Junit规则与androidx.arch.core:core-testing捆绑在一起,称为InstantTaskExecutorRule,另请参见:https://developer.android.com/reference/androidx/arch/core/executor/testing/InstantTaskExecutorRuleMutableLiveData is null in JUnitTest

如果您使用Junit 5 Jupiter,那么据我所知,任何Android库都没有附带扩展名,但是您可以轻松创建自定义扩展名:

class LiveDataInstantExecutorExtension : BeforeEachCallback, AfterEachCallback {

    override fun beforeEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance()
            .setDelegate(object : TaskExecutor() {
                override fun executeOnDiskIO(runnable: Runnable) = runnable.run()

                override fun postToMainThread(runnable: Runnable) = runnable.run()

                override fun isMainThread(): Boolean = true
            })
    }

    override fun afterEach(context: ExtensionContext?) {
        ArchTaskExecutor.getInstance().setDelegate(null)
    }
}

[如果您在androidx.arch.core.executor.testing.InstantTaskExecutorRule中检查Junit 4吊坠的实现,您会注意到我所做的与原始版本没有什么不同,只创建了Junit 5扩展而不是Junit规则

© www.soinside.com 2019 - 2024. All rights reserved.