Maven的单元测试

1. 单元测试的基本概念

单元测试(Unit Testing) 是一种软件测试方法,专注于测试程序中的最小可测试单元------通常是单个类或方法。通过单元测试,可以确保每个模块按预期工作,从而提高代码的质量和可靠性。

2.安装和配置 JUnit 5

使用 Maven 配置 JUnit 5

首先,在项目的 pom.xml 文件中添加 JUnit 5 的依赖项。

java 复制代码
<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,我们将为其编写单元测试。

java 复制代码
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

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;
    }
}

运行结果:

java 复制代码
private MathUtils mathUtils;

@BeforeEach
void setUp() {
    mathUtils = new MathUtils();
}
  • @BeforeEach 注解表示该方法在每个测试方法执行前都会被调用,用于初始化测试对象。

编写测试方法:

  • 测试加法
java 复制代码
@Test
void testAdd() {
    assertEquals(5, mathUtils.add(2, 3), "2 + 3 should equal 5");
}
  • @Test 注解表示这是一个测试方法。
  • assertEquals(expected, actual, message) 断言期望值与实际值相等,并提供自定义消息。

测试减法:

java 复制代码
@Test
void testSubtract() {
    assertEquals(-1, mathUtils.subtract(2, 3), "2 - 3 should equal -1");
}

测试除法:

java 复制代码
@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 支持参数化测试,允许你使用不同的输入数据多次运行同一个测试方法。

java 复制代码
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;

    @BeforeEach
    void 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 允许你在运行时动态生成测试用例。

java 复制代码
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;

    @BeforeEach
    void setUp() {
        mathUtils = new MathUtils();
    }

    @TestFactory
    Stream<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))
                )
            );
    }
}
相关推荐
zm15 分钟前
C基础寒假练习(4)
java·前端·数据库
hamster202140 分钟前
力扣【501. 二叉搜索树中的众数】Java题解
java·算法·leetcode
落幕1 小时前
C语言-运算符
java·开发语言
就很对1 小时前
6.进程的使用方式
java·linux·jvm
ccmedu1 小时前
Mac cursor设置jdk、Maven版本
jdk·maven·cursor
biubiubiu07061 小时前
使用Redis生成全局唯一ID示例
java·数据库·redis
萌新小码农‍1 小时前
回顾Maven
java·maven
潜水阿宝1 小时前
微服务网关鉴权之sa-token
java·spring boot·微服务·gateway·springcloud
gentle_ice2 小时前
leetcode——排序链表(java)
java·leetcode·链表
CHANG_THE_WORLD2 小时前
C++并发编程指南07
java·jvm·c++