面试题答案
一键面试使用IdlingResource
- 定义IdlingResource:
假设我们有一个网络请求的异步任务,在
ViewModel
中发起。首先定义一个CountingIdlingResource
。
class NetworkIdlingResource {
companion object {
private const val RESOURCE = "NETWORK"
val idlingResource: CountingIdlingResource = CountingIdlingResource(RESOURCE)
}
}
- 在异步任务中控制IdlingResource:
在发起网络请求前调用
idlingResource.increment()
,请求完成后调用idlingResource.decrement()
。例如在ViewModel
中:
class MyViewModel : ViewModel() {
init {
NetworkIdlingResource.idlingResource.increment()
viewModelScope.launch {
try {
// 模拟网络请求
delay(2000)
// 网络请求成功处理
} catch (e: Exception) {
// 网络请求失败处理
} finally {
NetworkIdlingResource.idlingResource.decrement()
}
}
}
}
- 在测试中注册IdlingResource:
@RunWith(AndroidJUnit4::class)
class MyUITest {
@get:Rule
val activityScenarioRule = ActivityScenarioRule(MyActivity::class.java)
@Before
fun registerIdlingResource() {
Espresso.registerIdlingResources(NetworkIdlingResource.idlingResource)
}
@After
fun unregisterIdlingResource() {
Espresso.unregisterIdlingResources(NetworkIdlingResource.idlingResource)
}
@Test
fun testAsyncTask() {
onView(withId(R.id.some_view)).check(matches(isDisplayed()))
}
}
使用Espresso的默认等待机制
Espresso有默认的等待机制,它会等待视图渲染完成。如果异步任务更新的视图在布局中,并且视图的状态变化是可见的(例如TextView
的文本更新),可以直接使用Espresso的断言。
@RunWith(AndroidJUnit4::class)
class MyUITest {
@get:Rule
val activityScenarioRule = ActivityScenarioRule(MyActivity::class.java)
@Test
fun testAsyncTaskWithDefaultWait() {
// 假设异步任务更新了一个TextView的文本
onView(withId(R.id.text_view)).check(matches(withText("Expected Text")))
}
}
Espresso会在一定时间内(默认超时时间为1000毫秒)等待视图达到预期状态。如果需要自定义等待时间,可以使用ViewInteraction.pollingTimeout
方法。
@Test
fun testAsyncTaskWithCustomTimeout() {
onView(withId(R.id.text_view))
.pollingTimeout(3000)
.check(matches(withText("Expected Text")))
}