Skip to content

Junit5超时处理

JUnit5 超时处理

简介

JUnit 5 提供了超时处理功能,用于设置测试方法的最大执行时间。如果测试方法的执行时间超过指定的超时时间,JUnit 5 将中断测试方法的执行,并将其标记为失败。

  • 测试过程中如果某条测试用例执行过程中阻塞,就会发生超时问题。
    • 阻塞其他用例的执行。
    • 对于某些用例,如果用例执行时间过长,超出正常执行范围,用例本身可能存在问题。

使用场景

  • 使用 JUnit5 自带的超时处理。当测试用例执行时间超过设置的执行时间,那么用例结果为执行失败。

@Timeout 注解

1. 单独使用 Timeout 注解

  • 使用@Timeout(5)注解配置超时时间,括号中的参数为设置的超时时间,单位为秒,而强制等待 sleep()单位为毫秒。
  • 代码实例

    package junit5.timeout;
    
    import org.junit.jupiter.api.Test;
    import org.junit.jupiter.api.Timeout;
    
    import static java.lang.Thread.sleep;
    
    public class TimeoutExampleTest {
        @Test
        //设定用例执行的超时时间,一旦超过x秒,则用例失败
        @Timeout(3)//单位为秒
        void timeoutDemo1() throws InterruptedException {
            sleep(10000);//单位为毫秒,强制等待10秒,超出超时时间,测试失败
            System.out.println("超时用例1");
        }
    
        @Test
        @Timeout(3)//单位为秒
        void timeoutDemo2(){
            System.out.println("超时用例2");//正常执行时间在3s内,测试通过
        }
    }
    
  • timeoutDemo1 方法中强制等待 10 秒钟,而我们设定的超时时间为 3 秒,运行超时,测试不通过,而 timeoutDemo2 方法正常执行时间在 3 秒之内,测试通过。

2.@Timeout 注解结合@BeforeEach@AfterEach注解

  • 我们依旧沿用上方的代码,先添加@BeforeEach注解
    • @Timeout注解结合@BeforeEach注解
    • 代码示例
          @BeforeEach//在每次测试执行之前执行
          @Timeout(3)//设定用例执行的超时时间,一旦超过3秒,则用例失败
          void setup() throws InterruptedException {
              sleep(40000);//强制等待4秒
              System.out.println("开始测试");
          }
      
    • 未添加@BeforeEach注释之前的测试方法执行结果如上图,timeoutDemo1方法未通过,timeoutDemo2方法通过;添加@BeforeEach注释后,两个测试方法均未通过,原因是我们在set up方法中强制等待的时间超出了超时时间,所以原本可以通过的timeoutDemo2方法也失败了。
    • 将 setup 方法中的强制等待时间注释,再执行查看结果,可以观察到,将等待时间注释之后,测试方法正常执行。所以@Timeout 注解结合@BeforeEach结合使用可以在创建测试所需的对象、初始化数据时测试超时时间。
  • 在之前代码的基础上,添加@AfterEach注解

    • @Timeout注解结合@AfterEach注解
    • 代码示例
        @AfterEach
        @Timeout(3)
        void teardown() throws InterruptedException {
            sleep(40000);
            System.out.println("结束测试");
        }
    
    • 添加@AfterEach注释在 teardown 方法中添加等待时间,两个测试方法均未通过,timeoutDemo1方法失败的原因是方法执行时超出了超时时间,原本可以通过的timeoutDemo2方法失败是因为 teardown 函数执行超时。
    • 将 teardown 方法中的强制等待时间注释,再执行查看结果,可以观察到,将等待时间注释之后,测试方法正常执行。所以@Timeout 注解结合@BeforeEach结合使用可以在回收数据,进行数据清洗等操作时测试超时时间。
  • 代码实例

    package junit5.timeout;
    
    import org.junit.jupiter.api.*;
    
    import static java.lang.Thread.sleep;
    
    public class TimeoutExampleTest {
    
        @BeforeEach//在每次测试执行之前执行
        @Timeout(3)//设定用例执行的超时时间,一旦超过3秒,则用例失败
        void setup() throws InterruptedException {
            //sleep(40000);//强制等待4秒
            System.out.println("开始测试");
        }
        @AfterEach
        @Timeout(3)
        void teardown() throws InterruptedException {
            sleep(40000);
            System.out.println("结束测试");
        }
        @Test
        //设定用例执行的超时时间,一旦超过x秒,则用例失败
        @Timeout(3)//单位为秒
        void timeoutDemo1() throws InterruptedException {
            sleep(10000);//单位为毫秒,强制等待10秒,超出超时时间,测试失败
            System.out.println("超时用例1");
        }
    
        @Test
        @Timeout(3)//单位为秒
        void timeoutDemo2(){
            System.out.println("超时用例2");//正常执行时间在3s内,测试通过
        }
    }
    

@Timeout 注解时间单位配置表

@Timeout注解的默认超时时间单位为秒(s),除此之外还可以手动设置时间单位。 | 时间 | 配置内容 | | ---------- | ------------ | | 42 毫秒 | @Timeout(value = 42, unit = MILLISECONDS) | | 42 秒 | @Timeout(value = 42, unit = SECONDS) | | 42 分 | @Timeout(value = 42, unit = MINUTES) | | 42 小时 | @Timeout(value = 42, unit = HOURS) | | 42 天 | @Timeout(value = 42, unit = DAYS) |


配置时间单位

  • 接下来以MILLISECONDS为时间单位为例,在@Timeout注解中添加时长和单位。
    @Test
    //`TimeUnit.MILLISECONDS` 和 `MILLISECONDS` 的本质是相同的,都代表时间单位是毫秒,这里使用效果无差别。
    @Timeout(value = 3, unit = TimeUnit.MILLISECONDS)
    void failsIfExecutionTimeExceeds100Milliseconds() {
    }
  • 测试方法中没有需要执行的操作,所以执行时间在超时范围内,测试通过。
  • 在测试方法中添加等待时间,再次执行对比结果,可以看到测试方法中等待时间已经为 5 毫秒,超出我们要求的超时时间,测试失败。
  • 代码实例

    package junit5.timeout;
    
    import org.junit.jupiter.api.*;
    
    import java.util.concurrent.TimeUnit;
    
    import static java.lang.Thread.sleep;
    
    public class TimeoutExampleTest {
        // 如果超过5秒则执行失败
        @BeforeEach
        @Timeout(5)
        void setUp() {
        }
        // 通过value参数配置数量,通过unit参数配置时间单位
        @Test
        //`TimeUnit.MILLISECONDS` 和 `MILLISECONDS` 的本质是相同的,都代表时间单位是毫秒,这里使用效果无差别。
        @Timeout(value = 3, unit = TimeUnit.MILLISECONDS)
        void failsIfExecutionTimeExceeds100Milliseconds() throws InterruptedException {
            sleep(5);//这里等待的时间单位是毫秒
        }
    }