2. JUnit 5中的测试方法排序
在JUnit 5中,我们可以使用@TestMethodOrder
注解来控制测试的执行顺序。支持三种内置排序方式:
- 字母数字顺序
@Order
注解- 随机顺序
2.1. 使用字母数字顺序
JUnit 5提供内置的MethodOrderer
实现,可按字母数字顺序运行测试。例如MethodOrderer.MethodName
会根据方法名和形参列表排序:
@TestMethodOrder(MethodOrderer.MethodName.class)
public class AlphanumericOrderUnitTest {
private static StringBuilder output = new StringBuilder("");
@Test
void myATest() {
output.append("A");
}
@Test
void myBTest() {
output.append("B");
}
@Test
void myaTest() {
output.append("a");
}
@AfterAll
public static void assertOutput() {
assertEquals("ABa", output.toString());
}
}
⚠️ 注意:MethodOrderer.Alphanumeric
已废弃,将在6.0版本移除。
2.2. 使用@Order
注解
通过@Order
注解强制按指定顺序执行测试:
@TestMethodOrder(OrderAnnotation.class)
public class OrderAnnotationUnitTest {
private static StringBuilder output = new StringBuilder("");
@Test
@Order(1)
void firstTest() {
output.append("a");
}
@Test
@Order(2)
void secondTest() {
output.append("b");
}
@Test
@Order(3)
void thirdTest() {
output.append("c");
}
@AfterAll
public static void assertOutput() {
assertEquals("abc", output.toString());
}
}
2.3. 使用随机顺序
使用MethodOrderer.Random
实现伪随机排序:
@TestMethodOrder(MethodOrderer.Random.class)
public class RandomOrderUnitTest {
private static StringBuilder output = new StringBuilder("");
@Test
void myATest() {
output.append("A");
}
@Test
void myBTest() {
output.append("B");
}
@Test
void myCTest() {
output.append("C");
}
@AfterAll
public static void assertOutput() {
assertEquals("ACB", output.toString());
}
}
⚠️ 默认使用System.nanoTime()
作为随机种子,可能导致重复运行时顺序不一致。可通过配置固定种子解决:
junit.jupiter.execution.order.random.seed=100
2.4. 使用自定义顺序
实现MethodOrderer
接口创建自定义排序器:
public class CustomOrder implements MethodOrderer {
@Override
public void orderMethods(MethodOrdererContext context) {
context.getMethodDescriptors().sort(
(MethodDescriptor m1, MethodDescriptor m2)->
m1.getMethod().getName().compareToIgnoreCase(m2.getMethod().getName()));
}
}
使用方式:
@TestMethodOrder(CustomOrder.class)
public class CustomOrderUnitTest {
// 测试方法...
@AfterAll
public static void assertOutput() {
assertEquals("AaB", output.toString());
}
}
2.5. 设置默认排序
通过junit-platform.properties
配置全局默认排序器:
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$DisplayName
✅ 此配置将应用于**所有未使用@TestMethodOrder
**的测试类。
3. JUnit 4中的测试方法排序
3.1. 使用MethodSorters.DEFAULT
默认策略基于哈希值排序,冲突时按字典序:
@FixMethodOrder(MethodSorters.DEFAULT)
public class DefaultOrderOfExecutionTest {
private static StringBuilder output = new StringBuilder("");
@Test
public void secondTest() {
output.append("b");
}
@Test
public void thirdTest() {
output.append("c");
}
@Test
public void firstTest() {
output.append("a");
}
@AfterClass
public static void assertOutput() {
assertEquals(output.toString(), "cab");
}
}
3.2. 使用MethodSorters.JVM
使用JVM自然排序,每次运行顺序可能不同:
@FixMethodOrder(MethodSorters.JVM)
public class JVMOrderOfExecutionTest {
// 测试方法同上
}
3.3. 使用MethodSorters.NAME_ASCENDING
按方法名字典序排序:
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NameAscendingOrderOfExecutionTest {
// 测试方法同上
@AfterClass
public static void assertOutput() {
assertEquals(output.toString(), "abc");
}
}
4. 使用@TestClassOrder
控制测试类顺序
JUnit 5提供ClassOrderer
接口支持测试类排序,支持以下方式:
ClassName
- 按类名排序DisplayName
- 按显示名排序OrderAnnotation
- 按@Order
注解排序Random
- 随机排序- 自定义排序
4.1. 使用ClassName
按类名字母顺序执行:
@TestClassOrder(ClassOrderer.ClassName.class)
public class ClassNameOrderUnitTest {
@Nested
class C extends TestC {}
@Nested
class B extends TestB {}
@Nested
class A extends TestA {}
}
输出:
Running TestA
Running TestB
Running TestC
4.2. 使用DisplayName
按显示名排序(未设置时回退到类名):
@TestClassOrder(ClassOrderer.DisplayName.class)
public class DisplayNameOrderUnitTest {
@Nested
@DisplayName("Class C")
class Z extends TestC {}
@Nested
@DisplayName("Class B")
class A extends TestA {}
@Nested
@DisplayName("Class A")
class B extends TestB {}
}
输出:
Running TestB
Running TestA
Running TestC
4.3. 使用OrderAnnotation
通过@Order
指定优先级:
@TestClassOrder(ClassOrderer.OrderAnnotation.class)
public class OrderAnnotationUnitTest {
@Nested
@Order(3)
class A extends TestA {}
@Nested
@Order(1)
class B extends TestB {}
@Nested
@Order(2)
class C extends TestC {}
}
输出:
Running TestB
Running TestC
Running TestA
4.4. 随机顺序
使用随机排序检测测试依赖:
@TestClassOrder(ClassOrderer.Random.class)
public class RandomOrderUnitTest {
@Nested
class C extends TestC {}
@Nested
class B extends TestB {}
@Nested
class A extends TestA {}
}
运行1输出:
Running TestA
Running TestC
Running TestB
运行2输出:
Running TestC
Running TestA
Running TestB
4.5. 使用自定义顺序
实现ClassOrderer
接口创建自定义排序器:
public class CustomClassOrderer implements ClassOrderer {
@Override
public void orderClasses(ClassOrdererContext context) {
context.getClassDescriptors().sort(
Comparator.comparingInt(descriptor ->
descriptor.getTestClass().getSimpleName().length()
)
);
}
}
使用方式:
@TestClassOrder(CustomClassOrderer.class)
public class CustomOrderUnitTest {
@Nested
class Longest extends TestA {}
@Nested
class Middle extends TestB {}
@Nested
class Short extends TestC {}
}
输出(按类名长度排序):
Running TestC
Running TestB
Running TestA
5. 总结
本文系统介绍了JUnit中控制测试执行顺序的各种方法:
- JUnit 5支持
@TestMethodOrder
和@TestClassOrder
注解 - 提供字母数字、注解、随机等多种内置排序策略
- 可通过实现接口创建自定义排序逻辑
- JUnit 4使用
@FixMethodOrder
实现类似功能
合理使用测试排序能帮助发现隐藏的测试依赖问题,提升测试可靠性。但需注意过度依赖执行顺序可能掩盖测试设计缺陷。