【问题标题】:Kotlin equivalent of Swift Expectations/PromisesKotlin 等价于 Swift 期望/承诺
【发布时间】:2019-04-16 21:06:08
【问题描述】:

我正在尝试为我的原生移动应用程序编写一些 UnitTest,但在我的 Android 测试中遇到了障碍。具体来说,我正在努力寻找 Kotlin 版本的 Swift 期望/承诺的示例。

我找到了 Kotlin Promises 的示例,但它们似乎比需要的复杂得多......

例如,下面是我iOS项目中登录API函数的测试:

func testLogin() {

    /// Prepare for login
    if CURRENT_USER != nil {
        logout()
    }

    /// Login
    let promise = expectation(description: "User is logged in.")

    // 1. Given
    var isSuccess: Bool = false

    // 2. When
    User.login(username: maleUsername, password: malePassword, success: {
        isSuccess = true
        promise.fulfill()
    }) { (_, agreeToTerms) in
        XCTFail()
    }
    wait(for: [promise], timeout: maxTimeOut)

    // 3. Then
    XCTAssertNotNil(CURRENT_USER)
    XCTAssertTrue(isSuccess)

    /// Logout
    logout()
}

这对我来说很简单。我有一个异步方法login,它有两个可能的完成块:successfailure;在评估之前,我需要等待其中一个完成。为此,我在调用之前创建了一个 promise,然后在两个完成块中履行承诺,然后我等待承诺在运行我的断言之前完成。

现在在 Kotlin 中,我有一个类似的测试:

private val loginFragment = LoginFragment()

@Test
fun loginTest() {

    val username = ""
    val password = ""

    // TODO: Create Promise

    loginFragment.loginViewModel
            .login(username, password)
            .observe(loginFragment, Observer {
                loginFragment.activity?.onResult(it?.result,

                        onSuccess = {
                            // TODO: Fill Promise
                        },
                        onValidationError = {
                            // TODO: Fail Test
                        })
            })

    // TODO: Assertions

}

但我找不到 swift 的承诺的等价物..

在 Kotlin 中存在吗?如果没有,我将如何在 Kotlin 中实现我的 Swift testLogin 方法的一个版本?

【问题讨论】:

  • 这可能会有所帮助:medium.com/@tonyowen/…
  • 在 Kotlin-Android 上最直接的 Promise 类比是普通的 CompletableFuture

标签: swift unit-testing kotlin promise kotlin-coroutines


【解决方案1】:

你可以使用 Kotlin 协程,例如:

@Test
fun loginTest() {
    val result = runBlocking {
        val loginResult = login() 
        loginResult
    }
    if (result == "Success") {
        // do your work when Success
    } else {
        // do your work when Error
    }
}
suspend fun login(): String = suspendCoroutine { continuation ->
    val username = ""
    val password = ""
    loginFragment.loginViewModel
    .login(username, password)
    .observe(loginFragment, Observer {
        loginFragment.activity?.onResult(it?.result,

                    onSuccess = {
                        continuation.resume("Success")
                    },
                    onValidationError = {
                        continuation.resume("Error") // take a look for other methods, e.g. resumeWithException(exception)

                    })
    })   
}

要使用协程,您需要在应用的 build.gradle 文件依赖项中添加下一行:

final KOTLIN_COROUTINES_VERSION = '1.0.1'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$KOTLIN_COROUTINES_VERSION"

希望它会有所帮助。

【讨论】:

  • 感谢您的信息。所以如果我要使用它,我基本上必须编写一个挂起函数和一个为每个测试运行挂起函数的函数?
  • 是的,这样代码更清晰易读。您可以通过将suspendCoroutine {} 块移动到runBlocking {} 中来避免创建login() 方法,但是代码中会出现一些混乱。
  • 两害相权取其轻……哈哈。
  • 我更喜欢用suspendCoroutine {}块创建一个新方法:)
  • 我将使用不同的方法。 Kotlin 有点蹩脚,因为您必须在 (A) 简洁但复杂、超嵌套、混乱的代码或 (B) 扩展但简单、可读、干净的代码之间做出选择。 Swift 看起来既干净又简洁
【解决方案2】:

我发现 this Kotlin Promise 库更接近 Swift Promises。 使用你的测试想要的这个库。

@Test
fun loginTest() {
    val username = ""
    val password = ""

    Promise<Boolean, Exception> { promise ->
        loginFragment.loginViewModel
            .login(username, password)
            .observe(loginFragment, Observer {
                loginFragment.activity?.onResult(it?.result,

                    onSuccess = {
                        promise.resolve(true)
                    },
                    onValidationError = {
                        promise.reject(Exception("Login error"))
                    })
            })
    }.whenComplete {
        when (it) {
            is Promise.Result.Success -> {
                assert(it.value)
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 2022-07-06
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 2018-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多