在 JUnit 5 中超过超时后如何使测试失败?
How to fail a test after a timeout is exceeded in JUnit 5?
在 JUnit 4 中,"timeout" 注释参数可用于强制测试在给定时间后停止:
@Test(timeout=100)
public void infinity() {
while(true);
}
如何在 JUnit 5 中完成此操作?
与 timeout parameter for Annotation Type Test 密切相关(代码取自)timeout parameter for Annotation Type Test,但适用于 JUnit 5。
使用来自 org.junit.jupiter.api.Assertions
的 assertTimeoutPreemptively
静态断言:
@Test
public void infinity() {
assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
while (true);
});
}
timeout
属性的严格等价物是声明性 @Timeout
注释。
From the JUnit 5 documentation :
The @Timeout
annotation allows one to declare that a test, test
factory, test template, or lifecycle method should fail if its
execution time exceeds a given duration. The time unit for the
duration defaults to seconds but is configurable.
例如:
@Test
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
void infinity() {
// fails if execution time exceeds 100 milliseconds
//...
}
Assertions.assertTimeout()
and Assertions.assertTimeoutPreemptively()
是 JUnit 5 中引入的新概念(JUnit 4 中不存在)。
这些是 @Timeout
的替代方法,将超时缩小到一组特定的语句:这些在 Executable
或 Supplier
中定义为参数传递。
这两种方法(名称非常接近)解决了相同的总体目标,但有细微的差别。
如果超时发生,assertTimeoutPreemptively()
抢先中止 Executable/Supplier
,而 assertTimeout()
没有。
为了实现它,assertTimeoutPreemptively()
在与调用代码不同的线程中执行提供的 Executable/Supplier
,而 assertTimeout()
在同一线程中执行它。
来自官方文档的警告:
Code/libraries 依赖 java.lang.ThreadLocal
存储进行测试执行 setup/teardown 可能会对 assertTimeoutPreemptively()
产生不良副作用,因为它会在不同的线程中执行提供的语句。
除了为特定测试指定超时的其他答案(根据 OP 请求),从 JUnit 5.5 开始,还可以配置全局超时,这是一个有用的选项,而不是添加 @Timeout
每个方法的注释。
根据 JUnit 5 User Guide,它记录了其他答案中的语法:
configuration parameters can be used to specify global timeouts for all methods of a certain category unless they or an enclosing test class is annotated with @Timeout
例如,这将为所有可测试和生命周期方法设置 500 毫秒的全局超时:
junit.jupiter.execution.timeout.default = 500 ms
超时的范围可以更窄,例如 @Test
方法:
junit.jupiter.execution.timeout.testtemplate.method.default = 500 ms
如果使用其他答案中描述的 @Timeout
注释,将覆盖这些默认值。
在 JUnit 4 中,"timeout" 注释参数可用于强制测试在给定时间后停止:
@Test(timeout=100)
public void infinity() {
while(true);
}
如何在 JUnit 5 中完成此操作?
与 timeout parameter for Annotation Type Test 密切相关(代码取自)timeout parameter for Annotation Type Test,但适用于 JUnit 5。
使用来自 org.junit.jupiter.api.Assertions
的 assertTimeoutPreemptively
静态断言:
@Test
public void infinity() {
assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
while (true);
});
}
timeout
属性的严格等价物是声明性 @Timeout
注释。
From the JUnit 5 documentation :
The
@Timeout
annotation allows one to declare that a test, test factory, test template, or lifecycle method should fail if its execution time exceeds a given duration. The time unit for the duration defaults to seconds but is configurable.
例如:
@Test
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
void infinity() {
// fails if execution time exceeds 100 milliseconds
//...
}
Assertions.assertTimeout()
and Assertions.assertTimeoutPreemptively()
是 JUnit 5 中引入的新概念(JUnit 4 中不存在)。
这些是 @Timeout
的替代方法,将超时缩小到一组特定的语句:这些在 Executable
或 Supplier
中定义为参数传递。
这两种方法(名称非常接近)解决了相同的总体目标,但有细微的差别。
如果超时发生,assertTimeoutPreemptively()
抢先中止 Executable/Supplier
,而 assertTimeout()
没有。
为了实现它,assertTimeoutPreemptively()
在与调用代码不同的线程中执行提供的 Executable/Supplier
,而 assertTimeout()
在同一线程中执行它。
来自官方文档的警告:
Code/libraries 依赖 java.lang.ThreadLocal
存储进行测试执行 setup/teardown 可能会对 assertTimeoutPreemptively()
产生不良副作用,因为它会在不同的线程中执行提供的语句。
除了为特定测试指定超时的其他答案(根据 OP 请求),从 JUnit 5.5 开始,还可以配置全局超时,这是一个有用的选项,而不是添加 @Timeout
每个方法的注释。
根据 JUnit 5 User Guide,它记录了其他答案中的语法:
configuration parameters can be used to specify global timeouts for all methods of a certain category unless they or an enclosing test class is annotated with @Timeout
例如,这将为所有可测试和生命周期方法设置 500 毫秒的全局超时:
junit.jupiter.execution.timeout.default = 500 ms
超时的范围可以更窄,例如 @Test
方法:
junit.jupiter.execution.timeout.testtemplate.method.default = 500 ms
如果使用其他答案中描述的 @Timeout
注释,将覆盖这些默认值。