Я пытаюсь использовать сопрограммы для обработки асинхронного кода для моей службы входа в систему. К сожалению, реализация службы входа в систему должна принимать обратные вызовы после ее завершения. Я не хочу, чтобы эта login()
функция выполнялась до тех пор, пока не произойдет один из этих обратных вызовов.
Вот что у меня есть:
fun login(): Outcome = runBlocking {
suspendCoroutine<Outcome> { continuation ->
loginService.login(
onLoginSuccess = {
// do some stuff
continuation.resume(Outcome.SUCCESS)
},
onLoginFailure = {
// handle failure case
continuation.resume(Outcome.FAILURE)
}
)
}
}
Моя проблема в том, что мои тесты никогда не заканчиваются. Я думаю, что происходит то, что сам блок продолжения не работает. Я попытался перевести вызов на uut.login()
в runBlocking, но это не помогло. Вот мой тестовый код (с использованием Spek):
describe("when login") {
val successCaptor: ArgumentCaptor<() -> Unit> = TestHelpers.argumentCaptorForClass()
val failureCaptor: ArgumentCaptor<() -> Unit> = TestHelpers.argumentCaptorForClass()
var result: Outcome? = null
beforeEachTest {
doNothing().whenever(mockLoginService)?.login(capture(successCaptor), capture(failureCaptor))
result = uut?.execute()
}
it("logs in with the login service") {
verify(mockLoginService)?.login(any(), any())
}
describe("and the login succeeds") {
beforeEachTest {
successCaptor.value.invoke()
}
// other tests...
it("returns an outcome of SUCCESS") {
expect(result).to.equal(Outcome.SUCCESS)
}
}
describe("and the login fails") {
beforeEachTest {
failureCaptor.value.invoke()
}
// other tests...
it("returns an outcome of FAILURE") {
expect(result).to.equal(Outcome.FAILURE)
}
}
}
По сути, я хотел бы заявить, что метод login()
возвратил либо результат УСПЕХА, либо ОТКАЗА, основываясь на произошедшем.
Есть идеи?