单元测试 WebView 的 WebViewClient 回调的 onPageStarted 和 onPageFinished
Unit testing the onPageStarted and onPageFinished of a WebView's WebViewClient callbacks
Android Studio 3.5.1
Kotlin 1.3
我尝试对以下方法进行单元测试。使用 WebView
和 WebViewClient
我的方法如下,需要进行单元测试:
fun setPageStatus(webView: WebView?, pageStatus: (PageStatusResult) -> Unit) {
webView?.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
pageStatus(PageStatusResult.PageStarted(url ?: "", favicon))
}
override fun onPageFinished(view: WebView?, url: String?) {
pageStatus(PageStatusResult.PageFinished(url ?: ""))
}
}
}
我使用了一个 webView,它覆盖了来自 WebViewClient 的一些回调。然后在 onPageStarted 或 onPageFinished 中调用一个 lambda 函数。
使用密封 class 设置在 lambda 方法中传递的属性
sealed class PageStatusResult {
data class PageFinished(val url: String) : PageStatusResult()
data class PageStarted(val url: String, val favicon: Bitmap?) : PageStatusResult()
}
在单元测试中我做了这样的事情:
@Test
fun `should set the correct settings of the WebView`() {
// Arrange the webView
val webView = WebView(RuntimeEnvironment.application.baseContext)
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when(pageStatusResult) {
is PageStarted -> {
// Assert that the url is correct
assertThat(pageStatusResult.url).isEqualToIgnoringCase("http://google.com")
}
}
}
// Call the onPageStarted on the webViewClient and and assert in the when statement
webView.webViewClient.onPageStarted(webView, "http://google.com", null)
}
由于此单元测试的性质是异步的,因此您应该使用异步测试方法,而不是自己同步调用 webView.webViewClient.onPageStarted
。这样,我们传一个URL给WebView
来显示,然后等onPageStarted
方法被WebView
自己调用。
运行 Android 中异步单元测试的最佳选择似乎是使用 Awaitility。
build.gradle
dependencies {
testImplementation 'org.awaitility:awaitility:4.0.1'
}
单元测试Class
@Test
fun `should set the correct settings of the WebView`() {
val requestedUrl = "https://www.google.com"
var resultUrl: String? = null
// Arrange the webView
val webView = WebView(RuntimeEnvironment.application.baseContext)
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when (pageStatusResult) {
is PageStatusResult.PageStarted -> {
resultUrl = pageStatusResult.url
}
}
}
// trying to load the "requestedUrl"
webView.loadUrl(requestedUrl)
// waiting until the "onPageStarted" is called
await().until { resultUrl != null }
// now check the equality of URLs
assertThat(resultUrl).isEqualToIgnoringCase(requestedUrl)
}
如果您正在使用 kotlinx-coroutines-test,您可以使用 CompletableDeferred
等待。
@Test
fun `should set the correct settings of the WebView`() = runTest {
val urlDeferred = CompletableDeferred<String>(coroutineContext.job)
// Arrange the webView
val webView = WebView(ApplicationProvider.getApplicationContext())
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when(pageStatusResult) {
is PageStatusResult.PageStarted -> {
urlDeferred.complete(pageStatusResult.url)
}
}
}
// Call the onPageStarted on the webViewClient and and assert in the when statement
webView.webViewClient.onPageStarted(webView, "http://google.com", null)
// Await at most MAX_WAITING milliseconds
val url = withTimeout(MAX_WAITING) { urlDeferred.await() }
// Assert that the url is correct
assertThat(url).isEqualToIgnoringCase("http://google.com")
}
Android Studio 3.5.1
Kotlin 1.3
我尝试对以下方法进行单元测试。使用 WebView
和 WebViewClient
我的方法如下,需要进行单元测试:
fun setPageStatus(webView: WebView?, pageStatus: (PageStatusResult) -> Unit) {
webView?.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
pageStatus(PageStatusResult.PageStarted(url ?: "", favicon))
}
override fun onPageFinished(view: WebView?, url: String?) {
pageStatus(PageStatusResult.PageFinished(url ?: ""))
}
}
}
我使用了一个 webView,它覆盖了来自 WebViewClient 的一些回调。然后在 onPageStarted 或 onPageFinished 中调用一个 lambda 函数。
使用密封 class 设置在 lambda 方法中传递的属性
sealed class PageStatusResult {
data class PageFinished(val url: String) : PageStatusResult()
data class PageStarted(val url: String, val favicon: Bitmap?) : PageStatusResult()
}
在单元测试中我做了这样的事情:
@Test
fun `should set the correct settings of the WebView`() {
// Arrange the webView
val webView = WebView(RuntimeEnvironment.application.baseContext)
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when(pageStatusResult) {
is PageStarted -> {
// Assert that the url is correct
assertThat(pageStatusResult.url).isEqualToIgnoringCase("http://google.com")
}
}
}
// Call the onPageStarted on the webViewClient and and assert in the when statement
webView.webViewClient.onPageStarted(webView, "http://google.com", null)
}
由于此单元测试的性质是异步的,因此您应该使用异步测试方法,而不是自己同步调用 webView.webViewClient.onPageStarted
。这样,我们传一个URL给WebView
来显示,然后等onPageStarted
方法被WebView
自己调用。
运行 Android 中异步单元测试的最佳选择似乎是使用 Awaitility。
build.gradle
dependencies {
testImplementation 'org.awaitility:awaitility:4.0.1'
}
单元测试Class
@Test
fun `should set the correct settings of the WebView`() {
val requestedUrl = "https://www.google.com"
var resultUrl: String? = null
// Arrange the webView
val webView = WebView(RuntimeEnvironment.application.baseContext)
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when (pageStatusResult) {
is PageStatusResult.PageStarted -> {
resultUrl = pageStatusResult.url
}
}
}
// trying to load the "requestedUrl"
webView.loadUrl(requestedUrl)
// waiting until the "onPageStarted" is called
await().until { resultUrl != null }
// now check the equality of URLs
assertThat(resultUrl).isEqualToIgnoringCase(requestedUrl)
}
如果您正在使用 kotlinx-coroutines-test,您可以使用 CompletableDeferred
等待。
@Test
fun `should set the correct settings of the WebView`() = runTest {
val urlDeferred = CompletableDeferred<String>(coroutineContext.job)
// Arrange the webView
val webView = WebView(ApplicationProvider.getApplicationContext())
// Act by calling the setPageStatus
webFragment.setPageStatus(webView) { pageStatusResult ->
when(pageStatusResult) {
is PageStatusResult.PageStarted -> {
urlDeferred.complete(pageStatusResult.url)
}
}
}
// Call the onPageStarted on the webViewClient and and assert in the when statement
webView.webViewClient.onPageStarted(webView, "http://google.com", null)
// Await at most MAX_WAITING milliseconds
val url = withTimeout(MAX_WAITING) { urlDeferred.await() }
// Assert that the url is correct
assertThat(url).isEqualToIgnoringCase("http://google.com")
}