Junit5 设置默认按声明顺序执行测试方法

59 阅读1分钟

前言

Junit5 中可以使用@TestMethodOrder 注解指定当前测试类的测试方法运行顺序

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ServiceTest {
   @Test
    @Order(1)
    void get() {}
    @Test
    @Order(2)
    void insert() {}
}

但是默认的MethodOrderer只有:
DisplayName(搭配@DisplayName)
MethodName
OrderAnnotation (搭配@Order)
Random

对于一些不太严格按照独立运行原则编写的单元测试,显式指定顺序有时候太过麻烦

最好的一种情况是默认测试方法可以按照声明顺序,或者说行号顺序排序,这就需要通过字节码读取来实现:

添加依赖

<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm</artifactId>
    <version>9.6</version>
    <scope>compile</scope>
</dependency>

实现自定义的行号排序MethodOrderer

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.MethodOrdererContext;
import org.objectweb.asm.*;

import java.io.IOException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class MethodLineOrder implements MethodOrderer {
    public void orderMethods(MethodOrdererContext context) {
        Class<?> testClass = context.getTestClass();
        Map<String, Integer> lineNumbers = getLineNumbers(testClass);

        context.getMethodDescriptors().sort(Comparator.comparingInt(
                descriptor -> lineNumbers.getOrDefault(descriptor.getMethod().getName(), Integer.MAX_VALUE)
        ));
    }

    private Map<String, Integer> getLineNumbers(Class<?> testClass) {
        Map<String, Integer> lineNumbers = new HashMap<>();
        try {
            ClassReader classReader = new ClassReader(testClass.getName());
            classReader.accept(new ClassVisitor(Opcodes.ASM9) {
                @Override
                public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
                    return new MethodVisitor(Opcodes.ASM9) {
                        @Override
                        public void visitLineNumber(int line, Label start) {
                            lineNumbers.put(name, line);
                            super.visitLineNumber(line, start);
                        }
                    };
                }
            }, 0);
        } catch (IOException e) {
            log.error("Error reading class: " + testClass, e);
        }
        return lineNumbers;
    }
}

将其指定为默认排序实现:

在项目的资源目录(src/test/resources)中新建文件junit-platform.properties

junit.jupiter.testmethod.order.default=com.your.MethodLineOrder