【问题标题】:Unit testing the onPageStarted and onPageFinished of a WebView's WebViewClient callbacks对 WebView 的 WebViewClient 回调的 onPageStarted 和 onPageFinished 进行单元测试
【发布时间】:2019-10-18 19:30:57
【问题描述】:
Android Studio 3.5.1
Kotlin 1.3

我尝试对以下方法进行单元测试。这使用WebViewWebViewClient

我的方法如下,需要进行单元测试:

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 ?: ""))
        }
    }
}

我采用了一个覆盖来自 WebViewClient 的一些回调的 webView。然后在 onPageStarted 或 onPageFinished 中调用一个 lambda 函数。

使用密封类来设置在 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)
}

【问题讨论】:

    标签: android unit-testing kotlin android-webview


    【解决方案1】:

    由于此单元测试的性质是异步的,因此您应该使用异步测试方法,而不是自己同步调用webView.webViewClient.onPageStarted。这样,我们将一个URL传递给WebView进行展示,然后等到onPageStarted方法被WebView自己调用。

    似乎在 Android 中运行异步单元测试的最佳选择是使用Awaitility

    build.gradle

    dependencies {
        testImplementation 'org.awaitility:awaitility:4.0.1'
    }
    

    单元测试类

    @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)
    }
    

    【讨论】:

    • 将 URL 更改为 https,因为如果没有网络安全配置,http 可能会失败。
    • 在没有 await() 的情况下有没有办法做到这一点?我正在考虑使用类似 doAnswer() 之类的东西
    • 很遗憾,如果不等待结果,我找不到可以做的事情。
    【解决方案2】:

    如果你使用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")
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-12
      相关资源
      最近更新 更多