我尝试编写UI测试,并遇到以下问题。我的测试:
lateinit var mockShootingApi: ShootingApi
@Before
fun setup() {
FragmentScenario.launchInContainer(MyFragment::class.java, null, object : FragmentFactory() {
override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
return MyFragment().apply {
isNotTesting = false
val realm = inMemoryRealm()
realm.executeTransaction { it.deleteAll() }
mockShootingApi = mock(ShootingApi::class.java)
val shootingRepository = ShootingRepository(mockShootingApi, realm)
viewModel = MyViewModel(ApplicationProvider.getApplicationContext(), shootingRepository)
}
}
})
}
@Test
fun test_null_response() {
runBlocking { `when`(mockShootingApi.fetchDataAsync(ArgumentMatchers.anyInt())).thenReturn(async { PageResult<Data>() })}
onView(withId(R.id.error_layout)).isVisible()
onView(withId(R.id.recyclerView)).isGone()
}
@Test
fun test_empty_response() {
runBlocking { `when`(mockShootingApi.fetchDataAsync(ArgumentMatchers.anyInt())).thenReturn(async { emptyPageResult() })}
onView(withId(R.id.error_layout)).isVisible()
onView(withId(R.id.recyclerView)).isGone()
onView(withId(R.id.error_text_view)).check(matches(withText("No results found")))
}
@Test
fun test_nonEmpty_response() {
runBlocking { `when`(mockShootingApi.fetcDataAsync(ArgumentMatchers.anyInt())).thenReturn(async { nonEmptyPageResult() }) }
onView(withId(R.id.error_layout)).isGone()
onView(withId(R.id.recyclerView)).isVisible()
onView(withId(R.id.recyclerView))
.check(matches(atPosition(0, withText("test title"), R.id.titleTextView)))
onView(withId(R.id.recyclerView))
.check(matches(atPosition(0, withText("test description"), R.id.descriptionTextView)))
}
因此,有时并非总是如此,只是在存储库调用shootingApi.fetchDataAsync()
出现的随机时刻,我得到了:
java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.Object kotlinx.coroutines.Deferred.await(kotlin.coroutines.Continuation)' on a null object reference
但同时shootingApi
实例被模拟,并且不为null。它是随机发生的,例如可以成功完成2-3次测试,然后失败1次,然后再次成功1次,失败1-2次。有人有一些“为什么”的想法吗?