Skip to content

JUnit 5 注解完整参考

涵盖生命周期、标记、条件执行、嵌套测试等所有注解


生命周期注解

@BeforeAll / @AfterAll

在整个测试类开始/结束时执行,必须是 static 方法

java
class DatabaseTest {

    private static Connection connection;

    @BeforeAll
    static void initAll() {
        // 只执行一次,用于全局初始化
        connection = DriverManager.getConnection(DB_URL);
        System.out.println("数据库连接建立");
    }

    @AfterAll
    static void cleanupAll() {
        // 测试类结束后清理资源
        connection.close();
        System.out.println("数据库连接关闭");
    }
}

@BeforeEach / @AfterEach

每个测试方法执行前后运行,非 static

java
class CalculatorTest {

    private Calculator calculator;

    @BeforeEach
    void setUp() {
        // 每个测试前创建新实例,确保测试隔离
        calculator = new Calculator();
    }

    @AfterEach
    void tearDown() {
        // 释放资源
        calculator = null;
    }
}

执行顺序图

@BeforeAll (static) ──────────────────────────────────▶ @AfterAll (static)
       │                                                       ▲
       ▼                                                       │
┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│    @BeforeEach   │ ──▶│   @Test (Test 1) │ ──▶│   @AfterEach    │
└──────────────────┘    └──────────────────┘    └──────────────────┘
       │                                                       ▲
       ▼                                                       │
┌──────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│    @BeforeEach   │ ──▶│   @Test (Test 2) │ ──▶│   @AfterEach    │
└──────────────────┘    └──────────────────┘    └──────────────────┘

测试标记注解

@Test

标记方法为测试方法,包名org.junit.jupiter.api.Test

java
@Test
@DisplayName("计算 1 + 1 应返回 2")
void onePlusOneShouldBeTwo() {
    assertEquals(2, 1 + 1);
}

@DisplayName

自定义测试/类的显示名称,支持中文、emoji、特殊字符。

java
@DisplayName("🧮 计算器功能测试")
class CalculatorTest {

    @Test
    @DisplayName("➕ 1 + 1 应该等于 2")
    void onePlusOneShouldBeTwo() { }

    @Test
    @DisplayName("➗ 除数不能为零")
    void divisionByZeroShouldThrow() { }
}

@Disabled

跳过指定的测试或类。

java
@Test
@Disabled("等待修复 #123 后再启用")
void flakyTest() { }

// 整个类禁用
@Disabled("已知问题,暂不使用")
class LegacyIntegrationTest { }

@Tag

为测试打标签,用于过滤执行。

java
@Test
@Tag("slow")
void integrationTest() { }

@Test
@Tag("fast")
void unitTest() { }

Maven 过滤执行:

xml
<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <groups>fast</groups>
        <excludedGroups>slow</excludedGroups>
    </configuration>
</plugin>

嵌套测试

@Nested 组织和分组相关测试。

java
@DisplayName("Stack 栈测试")
class StackTest {

    private Stack<Object> stack;

    @BeforeEach
    void setUp() {
        stack = new Stack<>();
    }

    @Nested
    @DisplayName("push 操作")
    class PushTests {
        @Test
        @DisplayName("向空栈 push 后大小为 1")
        void pushToEmptyStack() {
            stack.push("item");
            assertEquals(1, stack.size());
        }
    }

    @Nested
    @DisplayName("pop 操作")
    class PopTests {
        @Test
        @DisplayName("从空栈 pop 应抛出异常")
        void popFromEmptyShouldThrow() {
            assertThrows(EmptyStackException.class, stack::pop);
        }
    }
}

动态测试

@TestFactory 动态生成测试用例。

java
@TestFactory
@DisplayName("动态生成矩形面积测试")
Stream<DynamicTest> dynamicTests() {
    List<Rectangle> rectangles = List.of(
        new Rectangle(2, 3),
        new Rectangle(4, 5),
        new Rectangle(6, 7)
    );

    return rectangles.stream()
        .map(rect -> DynamicTest.dynamicTest(
            String.format("矩形 %d x %d = %d", 
                rect.width(), rect.height(), rect.area()),
            () -> assertEquals(
                rect.width() * rect.height(), 
                rect.area()
            )
        ));
}

条件执行注解

@EnabledOnOs / @DisabledOnOs

java
@Test
@EnabledOnOs(OS.LINUX)
void onlyOnLinux() { }

@Test
@DisabledOnOs({OS.WINDOWS, OS.MAC})
void notOnWindowsOrMac() { }

@EnabledOnJre / @DisabledOnJre

java
@Test
@EnabledOnJre({JRE.JAVA_17, JRE.JAVA_21})
void java17Or21Only() { }

@EnabledIf / @DisabledIf

java
@Test
@EnabledIfSystemProperty(named = "env", matches = "ci")
void onlyInCI() { }

@Test
@EnabledIfEnvironmentVariable(named = "DB_TYPE", matches = "mysql")
void mysqlOnly() { }

自定义条件

java
@EnabledIf("customCondition")
boolean customCondition() {
    return someRuntimeCheck();
}

测试实例生命周期

JUnit 5 支持两种测试实例生命周期:

模式说明
PER_METHOD(默认)每个测试方法创建新实例
PER_CLASS每个测试类创建单一实例
java
@DisplayName("PER_CLASS 生命周期模式")
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class PerClassTest {

    private int counter = 0;

    @BeforeAll
    void init() { // 不需要 static
        counter = 0;
    }

    @Test
    void first() {
        counter++;
        assertEquals(1, counter);
    }

    @Test
    void second() {
        counter++;
        assertEquals(2, counter);
    }
}

配置方式:

properties
# junit-platform.properties
junit.jupiter.testinstance.lifecycle.default = per_class

注解速查表

注解作用范围备注
@Test方法标记为测试方法
@DisplayName类/方法自定义显示名
@BeforeAll方法类生命周期前(static)
@AfterAll方法类生命周期后(static)
@BeforeEach方法方法生命周期前
@AfterEach方法方法生命周期后
@Nested非 static 类嵌套测试类
@Tag类/方法测试分组标签
@Disabled类/方法禁用测试
@TestFactory方法动态测试工厂
@TestTemplate方法多次调用模板
@RepeatedTest(n)方法重复执行 n 次
@TestInstance测试实例生命周期

相关页面

  • **Java\JUnit5-完全指南** - 返回总览
  • **Java\JUnit5-断言机制** - 断言详解
  • **Java\JUnit5-参数化测试** - 数据驱动
  • **Java\JUnit5-最佳实践** - 测试设计模式

#标签 #junit #注解 #annotation #lifecycle #testing

Knowledge4J — Java 知识库