小编cod*_*tim的帖子

kotlin协程使用withContext获取非阻塞代码时withTimeout不会取消

我正在使用 withContext 将函数转换为不会阻塞调用线程的挂起函数。为此,我使用https://medium.com/@elizarov/blocking-threads-suspending-coroutines-d33e11bf4761作为参考。

现在我想调用这个函数并设置超时。为此,我使用 withTimeout 来调用该函数,如下所示:

@Test
internal fun timeout() {
    runBlocking {
        logger.info("launching")
        try {
            withTimeout(1000) {
                execute()
            }
        } catch (e: TimeoutCancellationException) {
            logger.info("timed out", e)
        }
    }
}

private suspend fun execute() {
    withContext(Dispatchers.IO) {
        logger.info("sleeping")
        Thread.sleep(2000)
    }
}
Run Code Online (Sandbox Code Playgroud)

所以我期望的是,在 1000 毫秒后,异步启动的协程将被取消,并引发 TimeoutCancellationException。
但发生的情况是,完整的 2000 毫秒经过,当协程完成时,抛出异常:

14:46:29.231 [main @coroutine#1] INFO btccCoroutineControllerTest - 启动
14:46:29.250 [DefaultDispatcher-worker-1 @coroutine#1] INFO btccCoroutineControllerTest - 睡眠
14:46:31.261 [main@coroutine#1] INFO btccCoroutineControllerTest - kotlinx.coroutines.TimeoutCancellationException 超时:在 kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:128) 在 kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:94) 在 kotlinx.coroutines 等待 1000 毫秒超时。 …

kotlin kotlin-coroutines

5
推荐指数
1
解决办法
1万
查看次数

spring-test MockMvc kotlin DSL 缺乏异步支持?

spring-test 添加了对 MockMvc DSL 的支持,可以在此处找到文档: https ://docs.spring.io/spring/docs/5.2.0.M1/spring-framework-reference/languages.html#mockmvc-dsl

当测试返回 CompletableFuture(或任何其他异步结果类型)的控制器时,使用 MockMvc 的测试需要先执行 MvcResult 的 asyncDispatch,然后才能断言主体。这可以在各种博客或 stackoverflow 问题中找到:

新的 DSL 似乎缺乏一种干净的方法来做到这一点。

例如,需要以下代码来执行 asyncDispatch:

@Test
internal fun call() {
    val mvcResult = mockMvc.get("/execute") {
        accept = APPLICATION_JSON
    }.andExpect {
        request { asyncStarted() }
    }.andReturn()
    mockMvc.perform(asyncDispatch(mvcResult))
        .andExpect(MockMvcResultMatchers.status().isOk)
        .andExpect(MockMvcResultMatchers.jsonPath("$.value", Is.`is`("test")))
}
Run Code Online (Sandbox Code Playgroud)

我是否缺少一些可以实现此功能的东西,或者这只是 DSL 中尚未得到很好的支持?

更新: 我尝试使用 ResultActionsDsl 上的扩展功能来改进这一点。

fun ResultActionsDsl.asyncDispatch(mockMvc: MockMvc):ResultActionsDsl {
    val mvcResult = andReturn()
    mockMvc.perform(MockMvcRequestBuilders.asyncDispatch(mvcResult))
    return this
}
Run Code Online (Sandbox Code Playgroud)

这使得可以将测试编写为:

@Test
internal fun call() {
    mockMvc.get("/execute") {
        accept = APPLICATION_JSON
    }.andExpect …
Run Code Online (Sandbox Code Playgroud)

spring spring-mvc spring-test

4
推荐指数
1
解决办法
1917
查看次数

spring mvc 控制器协程挂起函数抛出 IllegalStateException

Spring 5.2 为 spring-mvc 控制器带来了协程支持。然而,让它工作似乎并不那么简单。当我不断收到堆栈跟踪时。

我有以下控制器:

@RestController
class MyController {
    private val logger = LoggerFactory.getLogger(MyController::class.java)
    @RequestMapping(path = ["/execute"], method = [RequestMethod.GET])
    fun execute(): CompletableFuture<ResponseEntity<ControllerResult>> {
        return GlobalScope.future {
            logger.info(Thread.currentThread().name)
            delay(10)
            logger.info(Thread.currentThread().name)
            ResponseEntity.ok(ControllerResult("test"))
    }    
    @GetMapping(path = ["/executeCo"])
    suspend fun executeCo(): ResponseEntity<ControllerResult> {
        logger.info(Thread.currentThread().name)
        delay(10)
        logger.info(Thread.currentThread().name)
        return ResponseEntity.ok(ControllerResult("test"))
    }
}
Run Code Online (Sandbox Code Playgroud)

我正在用 junit 5 和 MockMvc 测试这个。从测试中可以调用 GET /execute 并完美返回。调用 GET /executeCo 会导致以下堆栈跟踪:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface kotlin.coroutines.Continuation

    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
    at …
Run Code Online (Sandbox Code Playgroud)

spring-mvc

4
推荐指数
1
解决办法
1272
查看次数