![](/img/trans.png)
[英]java.lang.NoClassDefFoundError on Espresso Test when including Robolectric
[英]Avoiding sleep in Robolectric/Espresso test
我正在使用 Robolectric 编写端到端测试,它会触发对 OkHttp MockWebServer 的MockWebServer
调用。 它看起来像这样:
val mockServer = MockWebServer()
launchFragmentInHiltContainer<LoginFragment>()
onView(withId(R.id.loginEditText)).perform(typeText("loginId"))
onView(withId(R.id.loginButton)).perform(click())
// At this point, the fragment's viewmodel starts an HTTP request using Retrofit/OkHttp
// The callback causes a LiveData viewmodel to post an event, which the fragment listens
// to, and updates the UI accordingly
val request = mockServer.takeRequest()
assertEquals("/login", req.path)
Thread.sleep(1000)
shadowOf(getMainLooper()).idle()
// Without the two lines above, the test reaches this point before
// the mock server is done calling back
onView(withId(R.id.loggedInView)).check(matches(isDisplayed()))
单击登录按钮后,如何确保服务器响应得到完全处理?
我不是 100% 确定,但尝试一次
像这样制作 Object
Object syncObject = new Object();
然后用这个替换你的Thread.sleep(1000)
synchronized (syncObject) {
syncObject.notify();
}
如果它不能正常工作,则将wait()代替notify() 。
您可以使用Espresso idling resources
(链接: 文档)来实现这一点并摆脱Thread.sleep()
这根本不是一个好的选择。 由于您使用的是Okhttp
,因此已经有一个库可以为您解决问题: Okhttp Idling Resource 。
您无需向代码中注入等待语句来检测请求的终止。 您可能很清楚Thread.sleep(X)
单独解决这个问题是一个非常糟糕的尝试,因为您的请求每次都发生变化,并且您可能等待不够或等待太多。
Idling Resources
是一个更好的尝试,但存在多个问题。 1)在每次检查队列是否为空(没有请求)之间,它会让你等待 5 秒。 当您执行大量测试时,这会很快堆积起来。 2)您需要更改您正在测试的代码以启用空闲资源。 3)它不适用于所有类型的异步请求。
我(和许多其他人)在 Espresso 中使用自定义重试 function 来解决这个问题。
下面的 function 检查条件是否成立,如果不成立,则在 X 毫秒后再次检查。 这样,您的测试将在请求完成后立即进行(而不是 IdlingResources 中的 5 秒等待时间)。 您需要做的就是等待在您的请求发送之前不成立的条件。
fun waitForCondition(matcher: Matcher<View>,
timeout: Long = 15000L,
condition: (View?) -> Boolean) {
require(timeout > 0) { "Require timeout>0" }
var success = false
lateinit var exception: NoMatchingViewException
val loopCounter = timeout / 250L
(0..loopCounter).forEach {
onView(matcher).check { view, noViewFoundException ->
if (condition(view)) {
success = true
return@check
} else {
Thread.sleep(250)
exception = noViewFoundException
}
}
if (success) {
return
}
}
throw exception
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.