我有一个
TextView
显示“正在加载”字符串,我需要等到该视图消失。我没有 Asynctask
的句柄,因为此方法在 IntentService
中运行,并在加载完成时发送广播。
知道如何在 Espresso 测试中等待视图状态的更改吗?我需要同样的一些字符串,这些字符串会改变并且需要等待。我以为是类似的呢
感谢您的帮助。网上的例子或常见问题解答并不多。
您可以定义一个 ViewAction,每 50 毫秒(或您选择的不同时间)循环一次主线程,直到 View 的可见性更改为 View.GONE 或达到最大时间。
请按照以下步骤来实现此目的。
定义ViewAction,如下:
/**
* A [ViewAction] that waits up to [timeout] milliseconds for a [View]'s visibility value to change to [View.GONE].
*/
class WaitUntilGoneAction(private val timeout: Long) : ViewAction {
override fun getConstraints(): Matcher<View> {
return any(View::class.java)
}
override fun getDescription(): String {
return "wait up to $timeout milliseconds for the view to be gone"
}
override fun perform(uiController: UiController, view: View) {
val endTime = System.currentTimeMillis() + timeout
do {
if (view.visibility == View.GONE) return
uiController.loopMainThreadForAtLeast(50)
} while (System.currentTimeMillis() < endTime)
throw PerformException.Builder()
.withActionDescription(description)
.withCause(TimeoutException("Waited $timeout milliseconds"))
.withViewDescription(HumanReadables.describe(view))
.build()
}
}
定义一个函数,在调用时创建此 ViewAction 的实例,如下所示:
/**
* @return a [WaitUntilGoneAction] instance created with the given [timeout] parameter.
*/
fun waitUntilGone(timeout: Long): ViewAction {
return WaitUntilGoneAction(timeout)
}
在测试方法中调用此ViewAction,如下所示:
onView(withId(R.id.loadingTextView)).perform(waitUntilGone(3000L))
按照这个概念运行,并类似地创建一个
WaitForTextAction
类,该类等待 TextView 的文本更改为某个值。但是,在这种情况下,您可能需要将 getConstraints() 函数返回的 Matcher 从 any(View::class.java)
更改为 any(TextView::class.java)
。
我是这样处理这个案例的:
public void waitForViewToDisappear(int viewId, long maxWaitingTimeMs) {
long endTime = System.currentTimeMillis() + maxWaitingTimeMs;
while (System.currentTimeMillis() <= endTime) {
try {
onView(allOf(withId(viewId), isDisplayed())).matches(not(doesNotExist()));
} catch (NoMatchingViewException ex) {
return; // view has disappeared
}
}
throw new RuntimeException("timeout exceeded"); // or whatever exception you want
}
注意:
matches(not(doesNotExist()))
是一种“noop”匹配器;它只是为了确保 onView
部分真正运行。您同样可以编写一个不执行任何操作的 ViewAction
并将其包含在 perform
调用中,但这会增加更多行代码,因此我采用这种方式。