我正在编写一个测试函数,它应该运行一个块或(当达到某个超时时)抛出一个异常。
我在Kotlin中使用Coroutines
尝试此操作,但结果却混合了Coroutines
和CompletableFuture
:
fun <T> runBlockWithTimeout(maxTimeout: Long, block: () -> T ): T {
val future = CompletableFuture<T>()
// runs the coroutine
launch { block() }
return future.get(maxTimeout, TimeUnit.MILLISECONDS)
}
这有效,但我不确定这是否是解决kotlin问题的预期方法。
我也尝试过其他方法:
runBlocking {
withTimeout(maxTimeout) {
block()
}
}
但是,block
调用时,这似乎不起作用,例如Thread.sleep(...)
CompletableFuture
方法是可行的还是更好的方法?
更新1 我想要实现的目标:
异步集成 - 测试代码(如从RabbitMq接收数据)应该以这样的方式进行测试:
var rabbitResults: List = ... // are filled async via RabbitListeners
...
waitMax(1000).toSucceed {
assertThat(rabbitResults).hasSize(1)
}
waitMax(1000).toSucceed {
assertThat(nextQueue).hasSize(3)
}
...
答案 0 :(得分:7)
withTimeout { ... }
旨在取消正在进行的超时操作,只有在相关操作可取消时才可以。
它与future.get(timeout, unit)
一起使用的原因是因为只有等待超时。它实际上不会以任何方式取消或中止您的后台操作,该操作在超时后仍然继续执行。
如果你想模仿coroutines的类似行为,你应该等待超时,如下所示:
val d = async { block() } // run the block code in background
withTimeout(timeout, unit) { d.await() } // wait with timeout
它工作正常,因为await
是一个可取消的功能,您可以通过阅读its API documentation进行验证。
但是,如果你想在超时时实际取消正在进行的操作,那么你应该以异步和可取消的方式实现你的代码。取消是合作,因此,要开始,您在代码中使用的基础库必须提供支持取消正在进行的操作的异步API。
您可以在coroutines guide的相应部分中阅读有关取消和超时的更多信息,并观看KotlinConf的Deep Dive into Coroutines如何将协同程序与异步库集成。