Z
ZHANK
实战进阶

JUnit 单元测试

学习 @Test、断言、生命周期、参数化测试、Mockito 入门

单元测试 JUnit

JUnit 5 是 Java 标准的测试框架,让测试变得简单。

学完本章你将: 掌握 @Test、断言、生命周期、参数化测试。


第一个测试

java
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;

class Calculator {
    public int add(int a, int b) { return a + b; }
    public int divide(int a, int b) { return a / b; }
}

class CalculatorTest {
    private Calculator calc;

    @BeforeEach
    void setUp() {
        calc = new Calculator(); // 每个测试前执行
    }

    @Test
    void testAdd() {
        assertEquals(5, calc.add(2, 3));
        assertEquals(0, calc.add(-1, 1));
    }

    @Test
    void testDivide() {
        assertThrows(ArithmeticException.class,
            () -> calc.divide(1, 0));
    }
}

常用断言

java
// 相等
assertEquals(expected, actual);
assertEquals(expected, actual, "自定义错误消息");

// 真假
assertTrue(condition);
assertFalse(condition);

// 非空
assertNotNull(object);
assertNull(object);

// 异常
assertThrows(IOException.class, () -> readFile("bad.txt"));

// 超时
assertTimeout(Duration.ofSeconds(1),
    () -> Thread.sleep(500));

// 批量断言
assertAll(
    () -> assertEquals(4, 2 + 2),
    () -> assertTrue("hello".length() > 3)
);

生命周期

java
class LifecycleTest {
    @BeforeAll
    static void beforeAll() {} // 所有测试前(只一次)

    @BeforeEach
    void beforeEach() {}        // 每个测试前

    @Test
    void test1() {}

    @Test
    void test2() {}

    @AfterEach
    void afterEach() {}         // 每个测试后

    @AfterAll
    static void afterAll() {}   // 所有测试后(只一次)
}

参数化测试

java
@ParameterizedTest
@CsvSource({
    "1, 2, 3",
    "-1, 1, 0",
    "100, 200, 300",
})
void testAdd(int a, int b, int expected) {
    assertEquals(expected, calc.add(a, b));
}

@ParameterizedTest
@ValueSource(strings = {"", "  ", "\t"})
void testBlank(String input) {
    assertTrue(input.isBlank());
}