如何在JUnit 5中超时后使测试失败?

23

在JUnit 4中,可以使用"timeout"注释参数来强制测试在给定时间后停止:

@Test(timeout=100)
public void infinity() {
   while(true);
}

Junit 5如何实现这个功能?

Annotation Type Test的超时参数密切相关(取自该问题的代码),但针对JUnit 5。

3个回答

37
timeout属性的严格等价物是声明性的@Timeout注解。
来自JUnit 5文档

@Timeout注解允许声明一个测试、测试工厂、测试模板或生命周期方法,在其执行时间超过给定持续时间时应该失败。持续时间的时间单位默认为秒,但是可以配置。

例如:

@Test
@Timeout(value = 100, unit = TimeUnit.MILLISECONDS)
void infinity() { 
  // fails if execution time exceeds 100 milliseconds
  //...
}

Assertions.assertTimeout()Assertions.assertTimeoutPreemptively() 是在JUnit 5中引入的新概念(在JUnit 4中不存在)。 这些是@Timeout的替代品,它们将超时限制缩小到特定的一组语句:由参数中传递的ExecutableSupplier中定义的语句。
这两种方法(名字非常相似)解决了同一个问题,但有微妙的差别。
assertTimeoutPreemptively() 如果超时发生,会预先终止Executable/Supplier的执行,而assertTimeout()则不会。
为了做到这一点,assertTimeoutPreemptively() 在与调用代码不同的线程中执行提供的Executable/Supplier,而assertTimeout()则在相同的线程中执行。

来自官方文档的警告: 如果代码/库依赖于java.lang.ThreadLocal存储来进行测试执行设置/拆卸,则使用assertTimeoutPreemptively()可能会产生不良影响,因为该语句在不同的线程中执行提供的语句。


1
JUnit 5 Jupiter非常需要一个全局(可配置)超时时间,可以将其放置在基本测试类中,以便其他类扩展,以便杀死流氓测试。这是JUnit 4.x中非常有用的功能。 - Deepak

8

使用来自org.junit.jupiter.api.AssertionsassertTimeoutPreemptively静态断言:

@Test
public void infinity() {
    assertTimeoutPreemptively(Duration.ofMillis(100), () -> {
        while (true);
    });
}

4
除了其它答案中为特定测试指定超时时间(按照OP的要求),从JUnit 5.5开始,还可以配置全局超时时间,这是一个有用的选项,而不必为每个方法添加@Timeout注释。
根据JUnit 5用户指南中记录语法的其它答案所述:

可以使用配置参数为某个类别的所有方法指定全局超时时间,除非它们或封闭测试类已经被注解@Timeout标记。

例如,这将为所有可测试和生命周期方法设置500毫秒的全局超时时间:
junit.jupiter.execution.timeout.default = 500 ms

超时时间可以更加具体化,例如只针对@Test方法:
junit.jupiter.execution.timeout.testtemplate.method.default = 500 ms

在其他答案中描述的@Timeout注释将覆盖这些默认值,如果使用它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接