【问题标题】:Call ktor http client asynchronously in a suspend function在挂起函数中异步调用 ktor http 客户端
【发布时间】:2021-08-02 18:24:33
【问题描述】:

我有以下使用 ktor 的 HttpClient 的函数。而tokenService getAccessToken 函数也使用ktor 客户端并获取令牌。

suspend fun addUser(user: User): User {
    return client.post("${Base}api/v1/adduser") {
        contentType(ContentType.Application.Json)
        header("Authorization", "Bearer ${tokenService.getAccessToken()}")
        body = user
    }
}

这是我的简单测试

@Test
fun `should add user`() = runBlocking {
    delay(3000)
    val user = userService.addUser(User("john doe"))
    user.firstName shouldBe "john doe"
}

现在测试由于延迟而通过,延迟为首先获取令牌提供了时间,但是如果我删除延迟,则调用 addUser 函数而不首先获取令牌。我的问题是,有没有更好的方法来做到这一点,以避免增加测试延迟。 我查看了 Kotlin Flows,但我不知道如何为我的场景实现它。 如果你能指出我正确的方向,我将不胜感激。

【问题讨论】:

  • 这很奇怪,因为如果我使用您的代码并延迟(出于测试目的)tokenService.getAccessToken() 方法,那么addUser 总是等待其完成。 tokenService.getAccessToken() 在您的测试中毫不拖延地返回什么?
  • 由于 tokenServcie.getAccessToken() 是网络调用,因此需要几秒钟。当您尝试它时,如果您只是返回一些文本进行测试,它会足够快,因此不会有任何问题。当我运行我的代码时,addUser 在没有令牌头的情况下被调用并抛出错误。
  • 这就是为什么我尝试设置足够大的延迟来模拟网络调用。这是按预期工作的类似代码gist.github.com/Stexxe/ce539589129e5e529d1c30564b0c7951

标签: kotlin ktor ktor-client


【解决方案1】:

这是一般单元测试的常见问题。想想当您必须向数据库发出请求时,我们不想启动整个数据库只是为了对其进行单元测试,这会使测试变得缓慢和繁琐。我们希望从我们的单元测试中获得快速反馈,而不是到处添加延迟。

一种常见的方法是使用 MockitoMockk 之类的模拟库来模拟网络服务(在您的情况下为 tokenService)。如果你使用 Mockito reference 你可以这样做:

val mockTokenService = Mockito.mock(TokenService::class.java)
Mockito.`when`(mockTokenService.getAccessToken()).thenReturn("sampleToken123")

这样你就可以从你的单元测试中删除delay(3000)。然后,如果测试通过,您将知道您的 addUser 方法业务逻辑将是正确的,并且您可以单独测试令牌服务,如果您愿意,可以使用更多参与的集成测试或其他模拟。

【讨论】:

    猜你喜欢
    • 2023-03-22
    • 2017-12-15
    • 2017-08-30
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    相关资源
    最近更新 更多