LiveData 在 ViewModel 测试期间返回 NullPointer IsMainThread 错误

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

在尝试观察视图模型中的实时数据时,我的视图模型单元测试一直失败。我从文档中添加了两条规则,即:InstantTaskExecutorRule 和 MainCoroutineRule。我还将自己的调度程序注入到视图模型中,以便我可以在测试中替换它。这是我的单元测试:

@ExperimentalCoroutinesApi
@FlowPreview
@RunWith(JUnit4::class)
class LaunchViewModelTest {

@get:Rule
var rule: TestRule = InstantTaskExecutorRule()

@get:Rule
var mainCoroutineRule = MainCoroutineRule()

private var launchOptions = mockk<LaunchOptions>(relaxed = true)
private var launchInteractors = mockk<LaunchInteractors>(relaxed = true)
private lateinit var companyInfoInteractors: CompanyInfoInteractors
private lateinit var viewModel: LaunchViewModel
private var dependencyContainer: LaunchDependencies = LaunchDependencies()
private var companyDependencyContainer: CompanyDependencies = CompanyDependencies()
private lateinit var dataStore: AppDataStoreManagerFake

@BeforeEach
fun setup() {
    dependencyContainer.build()
    companyDependencyContainer.build()
    dataStore = AppDataStoreManagerFake()
    companyInfoInteractors = companyDependencyContainer.companyInfoInteractors
}

@Test
fun getLaunchItemsFromNetwork() = runTest {
    viewModel = LaunchViewModel(
        ioDispatcher = Dispatchers.Unconfined,
        launchInteractors = launchInteractors,
        companyInfoInteractors = companyInfoInteractors,
        launchOptions = launchOptions,
        appDataStoreManager = dataStore
    )

    viewModel.setStateEvent(
        LaunchStateEvent.GetLaunchItemsFromNetworkAndInsertToCacheEvent(
            launchOptions = launchOptions
        )
    )

    val launchList = dependencyContainer.launchDataFactory.produceListOfLaunchItems()

    assertEquals(viewModel.viewState.getOrAwaitValueTest(), launchList)

}

错误发生在 getOrAwaitValueTest() 函数中,该函数是一个旨在观察实时数据的辅助类:

@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValueTest(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS,
afterObserve: () -> Unit = {}
): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
    override fun onChanged(o: T?) {
        data = o
        latch.countDown()
        [email protected](this)
    }
}
this.observeForever(observer)

try {
    afterObserve.invoke()

    // Don't wait indefinitely if the LiveData is not set.
    if (!latch.await(time, timeUnit)) {
        throw TimeoutException("LiveData value was never set.")
    }

} finally {
    this.removeObserver(observer)
}

@Suppress("UNCHECKED_CAST")
return data as T
}

错误:

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:486)
at androidx.lifecycle.LiveData.observeForever(LiveData.java:224)
at com.LiveDataUtilKt.getOrAwaitValueTest(LiveDataUtil.kt:47)
at com.LiveDataUtilKt.getOrAwaitValueTest$default(LiveDataUtil.kt:33)
android kotlin-coroutines android-livedata android-testing android-viewmodel
1个回答
0
投票

我知道这已经晚了,但对于那些仍然面临同样问题的人:检查类似问题的答案,这可能有帮助https://stackoverflow.com/a/49840604/10834775

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