1. 單元測試的基本概念
單元測試(Unit Testing) 是一種軟件測試方法,專注于測試程序中的最小可測試單元——通常是單個類或方法。通過單元測試,可以確保每個模塊按預期工作,從而提高代碼的質量和可靠性。
2.安裝和配置 JUnit 5
使用 Maven 配置 JUnit 5
首先,在項目的 pom.xml
文件中添加 JUnit 5 的依賴項。
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.example.myproject</groupId><artifactId>my-application</artifactId><version>1.0.0-SNAPSHOT</version><packaging>jar</packaging><name>My Application</name><description>A sample application using Maven and JUnit 5</description><dependencies><!-- 添加 JUnit 5 依賴 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.9.1</version><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.22.2</version></plugin></plugins></build>
</project>
3.編寫單元測試
示例項目結構
假設我們有一個簡單的數學工具類 MathUtils
,我們將為其編寫單元測試。
my-maven-project/
├── pom.xml
├── src/
│ ├── main/
│ │ └── java/
│ │ └── com/example/myproject/
│ │ └── MathUtils.java
│ └── test/
│ └── java/
│ └── com/example/myproject/
│ └── MathUtilsTest.java
創建?MathUtils
?類
src/main/java/com/example/myproject/MathUtils.java
package com.example.myproject;public class MathUtils {public int add(int a, int b) {return a + b;}public int subtract(int a, int b) {return a - b;}public double divide(int a, int b) {if (b == 0) {throw new IllegalArgumentException("Cannot divide by zero");}return (double) a / b;}public int multiply(int a, int b) {return a * b;}
}
運行結果:
?
private MathUtils mathUtils;@BeforeEach
void setUp() {mathUtils = new MathUtils();
}
@BeforeEach
?注解表示該方法在每個測試方法執行前都會被調用,用于初始化測試對象。
編寫測試方法:
-
測試加法
@Test
void testAdd() {assertEquals(5, mathUtils.add(2, 3), "2 + 3 should equal 5");
}
@Test
?注解表示這是一個測試方法。assertEquals(expected, actual, message)
?斷言期望值與實際值相等,并提供自定義消息。
測試減法:
@Test
void testSubtract() {assertEquals(-1, mathUtils.subtract(2, 3), "2 - 3 should equal -1");
}
測試除法:
@Test
void testDivide() {assertEquals(2.5, mathUtils.divide(5, 2), 0.001, "5 / 2 should equal 2.5");Exception exception = assertThrows(IllegalArgumentException.class, () -> {mathUtils.divide(1, 0);});assertEquals("Cannot divide by zero", exception.getMessage(), "Exception message should be 'Cannot divide by zero'");
}
assertThrows(exceptionType, executable)
?斷言拋出指定類型的異常。assertEquals(expected, actual, delta, message)
?用于比較浮點數時允許一定的誤差范圍。
高級特性
參數化測試
JUnit 5 支持參數化測試,允許你使用不同的輸入數據多次運行同一個測試方法。
package com.example.myproject;import static org.junit.jupiter.params.provider.Arguments.arguments;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;import java.util.stream.Stream;class MathUtilsTest {private MathUtils mathUtils;@BeforeEachvoid setUp() {mathUtils = new MathUtils();}@ParameterizedTest(name = "{index} => add({0}, {1}) = {2}")@MethodSource("addProvider")void testAdd(int a, int b, int expected) {assertEquals(expected, mathUtils.add(a, b));}private static Stream<Arguments> addProvider() {return Stream.of(arguments(2, 3, 5),arguments(-1, 1, 0),arguments(0, 0, 0));}
}
動態測試
JUnit 5 允許你在運行時動態生成測試用例。
package com.example.myproject;import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.DynamicNode;
import org.junit.jupiter.api.TestFactory;
import org.junit.jupiter.api.function.Executable;import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;import static org.junit.jupiter.api.DynamicTest.dynamicTest;class MathUtilsTest {private MathUtils mathUtils;@BeforeEachvoid setUp() {mathUtils = new MathUtils();}@TestFactoryStream<DynamicNode> dynamicTestsFromStream() {List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);return numbers.stream().map(number ->dynamicTest("multiply " + number + " by 2",() -> assertEquals(number * 2, mathUtils.multiply(number, 2))));}
}