前言
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