超时能挡住卡死的测试吗?这篇用 JUnit 5.11 把四种写法都跑了一遍:谁真的缩短了耗时,谁只是事后报告,放弃的线程会留下什么,以及超时设得太紧时机器一忙会怎样。
[SleepTO] 整个 JVM 用时 1.3 s
[ 0 ms] sleep 开始
[ 1010 ms] sleep 被中断
│ └─ sleeps3s() ✘ sleeps3s() timed out after 1 second
=> java.util.concurrent.TimeoutException: sleeps3s() timed out after 1 second
→ 0 tests successful | 1 tests failed
[BusyTO] 整个 JVM 用时 3.3 s
[ 0 ms] 忙等 3 秒开始(不检查中断)
[ 3005 ms] 忙等结束,方法返回
│ └─ busy3s() ✘ busy3s() timed out after 1 second
=> java.util.concurrent.TimeoutException: busy3s() timed out after 1 second
→ 0 tests successful | 1 tests failed [SepTO] 整个 JVM 用时 1.3 s
[ 0 ms] 忙等 3 秒开始,线程 非 main 线程
│ └─ busy3s() ✘ busy3s() timed out after 1 second
=> java.util.concurrent.TimeoutException: busy3s() timed out after 1 second
→ 0 tests successful | 1 tests failed
[SepTO + AfterTO 在同一个 JVM 里] 整个 JVM 用时 4.8 s
[ 0 ms] 忙等 3 秒开始,线程 非 main 线程
[ 1017 ms] 另一个测试开始(sleep 3.5 秒,模拟后面的测试)
[ 3006 ms] 忙等结束(测试早已被判失败)
[ 4528 ms] 另一个测试结束
│ │ └─ busy3s() ✘ busy3s() timed out after 1 second
=> java.util.concurrent.TimeoutException: busy3s() timed out after 1 second
→ 1 tests successful | 1 tests failed
[TlTO] 整个 JVM 用时 0.3 s
[ 0 ms] @BeforeEach 在 main 里设置 ThreadLocal
[ 7 ms] SAME_THREAD(默认):在 main 里读到 ThreadLocal = 事务上下文
[ 11 ms] @BeforeEach 在 main 里设置 ThreadLocal
[ 12 ms] SEPARATE_THREAD:在 另一个线程 里读到 ThreadLocal = null
→ 2 tests successful | 0 tests failed [AssertTO] 整个 JVM 用时 4.3 s
[ 0 ms] assertTimeoutPreemptively 开始(sleep 3 秒)
[ 1018 ms] lambda 被中断
[ 1030 ms] assertTimeout 开始(sleep 3 秒)
[ 4041 ms] assertTimeout 的 lambda 跑完了
│ ├─ preemptive() ✘ execution timed out after 1000 ms
│ └─ nonPreemptive() ✘ execution exceeded timeout of 1000 ms by 2010 ms
=> org.opentest4j.AssertionFailedError: execution timed out after 1000 ms
=> org.opentest4j.AssertionFailedError: execution exceeded timeout of 1000 ms by 2010 ms
→ 0 tests successful | 2 tests failed [NoAnno 不设默认超时] 整个 JVM 用时 3.3 s
[ 0 ms] @BeforeEach 卡住 3 秒(没有任何 @Timeout)
[ 3015 ms] @BeforeEach 结束
[ 3021 ms] test 运行
→ 1 tests successful | 0 tests failed
[NoAnno 默认超时 1s](配置 junit.jupiter.execution.timeout.default=1s) 整个 JVM 用时 1.3 s
[ 0 ms] @BeforeEach 卡住 3 秒(没有任何 @Timeout)
│ └─ t() ✘ hangs() timed out after 1 second
=> java.util.concurrent.TimeoutException: hangs() timed out after 1 second
→ 0 tests successful | 1 tests failed逻辑 CPU 10 个 空闲机器 第 1 次:成功 300、失败 0 空闲机器 第 2 次:成功 300、失败 0 空闲机器 第 3 次:成功 300、失败 0 满载机器(40 个空转进程)第 1 次:成功 8、失败 292 满载机器(40 个空转进程)第 2 次:成功 8、失败 292 满载机器(40 个空转进程)第 3 次:成功 4、失败 296