Kotlin 相当于 Swift Expectations/Promises
Kotlin equivalent of Swift Expectations/Promises
我正在尝试为我的本机移动应用程序编写一些单元测试,但在我的 Android 测试中遇到了 运行 障碍。具体来说,我正在努力寻找 Swift 的 Expectations/Promises..
的 Kotlin 版本的示例
我找到了 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
,它有两个可能的完成块:success
和 failure
;在评估之前,我需要等待其中一个完成。为此,我在调用之前创建了一个 promise,然后我 fulfill 两个完成块中的 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
方法的一个版本?
您可以使用 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"
希望对您有所帮助。
我发现 this Kotlin Promise lib 更接近 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)
}
}
}
}
我在 20 分钟内写了一个看起来像 swift 的 expectation
的实现,但他并不复杂,仅用于简单的情况就可以很好地工作。
typealias XCTestExceptionHandler = (KTTestException?) -> Unit
fun TestCase.expectation(description: String): KTTestExpectation {
return KTTestExpectation(description)
}
fun TestCase.waitFor(expectation: KTTestExpectation, timeout: Long, handler: XCTestExceptionHandler) {
expectation.handler = handler
Thread.sleep(timeout)
expectation.timedOut()
}
class KTTestExpectation(private val description: String) {
private var isFulfilled = false
var handler: XCTestExceptionHandler? = null
fun fulfill() {
Handler(Looper.getMainLooper()).postDelayed({
invokeHandlerWith(null)
}, 2)
}
fun timedOut() {
invokeHandlerWith(KTTestException("Timed out: $description"))
}
private fun invokeHandlerWith(error: KTTestException?) {
if (isFulfilled) return
isFulfilled = true
handler?.invoke(error)
error?.let { Assert.fail("Timed out: $description") }
}
}
class KTTestException(message:String): Exception(message)
使用:
fun testExpectation() {
var nb = 0
val expectation = expectation("Test")
MyAsyncFunc {
nb = 5
expectation.fulfill()
}
waitFor(expectation, 1000) { error ->
assertEquals(5, nb)
}
}
如果有人有勇气将原始代码转换为 Kotlin 链接如下:
https://github.com/apple/swift-corelibs-xctest/blob/main/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift
我正在尝试为我的本机移动应用程序编写一些单元测试,但在我的 Android 测试中遇到了 运行 障碍。具体来说,我正在努力寻找 Swift 的 Expectations/Promises..
的 Kotlin 版本的示例我找到了 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
,它有两个可能的完成块:success
和 failure
;在评估之前,我需要等待其中一个完成。为此,我在调用之前创建了一个 promise,然后我 fulfill 两个完成块中的 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
方法的一个版本?
您可以使用 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"
希望对您有所帮助。
我发现 this Kotlin Promise lib 更接近 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)
}
}
}
}
我在 20 分钟内写了一个看起来像 swift 的 expectation
的实现,但他并不复杂,仅用于简单的情况就可以很好地工作。
typealias XCTestExceptionHandler = (KTTestException?) -> Unit
fun TestCase.expectation(description: String): KTTestExpectation {
return KTTestExpectation(description)
}
fun TestCase.waitFor(expectation: KTTestExpectation, timeout: Long, handler: XCTestExceptionHandler) {
expectation.handler = handler
Thread.sleep(timeout)
expectation.timedOut()
}
class KTTestExpectation(private val description: String) {
private var isFulfilled = false
var handler: XCTestExceptionHandler? = null
fun fulfill() {
Handler(Looper.getMainLooper()).postDelayed({
invokeHandlerWith(null)
}, 2)
}
fun timedOut() {
invokeHandlerWith(KTTestException("Timed out: $description"))
}
private fun invokeHandlerWith(error: KTTestException?) {
if (isFulfilled) return
isFulfilled = true
handler?.invoke(error)
error?.let { Assert.fail("Timed out: $description") }
}
}
class KTTestException(message:String): Exception(message)
使用:
fun testExpectation() {
var nb = 0
val expectation = expectation("Test")
MyAsyncFunc {
nb = 5
expectation.fulfill()
}
waitFor(expectation, 1000) { error ->
assertEquals(5, nb)
}
}
如果有人有勇气将原始代码转换为 Kotlin 链接如下: https://github.com/apple/swift-corelibs-xctest/blob/main/Sources/XCTest/Public/Asynchronous/XCTWaiter.swift