当我单独运行 runAsyncWithMock
测试时,它会等待 3 秒直到模拟的执行完成,而不是像其他 2 个测试那样被终止。
我不明白为什么。
有趣的是:
runAsyncWithMock
测试中,CompletableFuture.runAsync
连续执行多个Runnable
时,只有第一个等待,其他不等待.- 当有多个重复的
runAsyncWithMock
测试时,在执行整个规范时,每个测试都会运行 3 秒。 - 当使用 Class 实例而不是 Mock 时,测试会立即完成。
知道我错了什么吗?
我的配置:
- macOS Mojave 10.14.6
- Spock 1.3-groovy-2.4
- 常规 2.4.15
- JDK 1.8.0_201
包含用于复制的整个 Gradle 项目的 repo:
https://github.com/lobodpav/CompletableFutureMisbehavingTestInSpock
有问题的测试代码:
@Stepwise
class SpockCompletableFutureTest extends Specification {
def runnable = Stub(Runnable) {
run() >> {
println "${Date.newInstance()} BEGIN1 in thread ${Thread.currentThread()}"
sleep(3000)
println "${Date.newInstance()} END1 in thread ${Thread.currentThread()}"
}
}
def "runAsyncWithMock"() {
when:
CompletableFuture.runAsync(runnable)
then:
true
}
def "runAsyncWithMockAndClosure"() {
when:
CompletableFuture.runAsync({ runnable.run() })
then:
true
}
def "runAsyncWithClass"() {
when:
CompletableFuture.runAsync(new Runnable() {
void run() {
println "${Date.newInstance()} BEGIN2 in thread ${Thread.currentThread()}"
sleep(3000)
println "${Date.newInstance()} END2 in thread ${Thread.currentThread()}"
}
})
then:
true
}
}
最佳答案
这是由 https://github.com/spockframework/spock/blob/master/spock-core/src/main/java/org/spockframework/mock/runtime/MockController.java 中的 synchronized
方法引起的当执行模拟时,它通过 handle
方法进行委托(delegate)。该规范还使用了 synchronized
方法,在本例中可能是 leaveScope
,因此被休眠 Stub 方法阻塞。
由于这是一个线程交错问题,我猜测 runAsyncWithMockAndClosure
中的附加闭包将 stub 方法的执行移到了 leaveScope
之后,从而改变了顺序/阻塞。
关于testing - 当由 CompletableFuture 运行时,在 Spock 的 Mock 等待中休眠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57869239/