Тестирование приостановки corotuine - PullRequest
0 голосов
/ 07 мая 2018

Я пытаюсь использовать сопрограммы для обработки асинхронного кода для моей службы входа в систему. К сожалению, реализация службы входа в систему должна принимать обратные вызовы после ее завершения. Я не хочу, чтобы эта 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() возвратил либо результат УСПЕХА, либо ОТКАЗА, основываясь на произошедшем.

Есть идеи?

1 Ответ

0 голосов
/ 07 мая 2018

Конечно, я понял это сразу после публикации.Если интересно, вот что я сделал в тесте:

describe("when login") {

    val successCaptor: ArgumentCaptor<() -> Unit> = TestHelpers.argumentCaptorForClass()
    val failureCaptor: ArgumentCaptor<() -> Unit> = TestHelpers.argumentCaptorForClass()

    var result: Outcome? = null

    describe("and the login succeeds") {

        beforeEachTest {
            whenever(mockLoginService?.login(capture(successCaptor), capture(failureCaptor))).thenAnswer {
                successCaptor.value.invoke()
            }
            result = uut?.execute()
        }

        it("logs in with the login service") {
            verify(mockLoginService)?.login(any(), any())
        }

        it("returns an outcome of SUCCESS") {
            expect(result).to.equal(Outcome.SUCCESS)
        }
    }

    describe("and the login fails") {
        beforeEachTest {
            whenever(mockLoginService?.login(capture(successCaptor), capture(failureCaptor))).thenAnswer {
                failureCaptor.value.invoke()
            }
            result = uut?.execute()
        }

        it("logs in with the login service") {
            verify(mockLoginService)?.login(any(), any())
        }

        // other tests

        it("returns an outcome of FAILURE") {
            expect(result).to.equal(Outcome.FAILURE)
        }
    }
}
...