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))
                )
            );
    }
}
相关推荐
缺点内向3 小时前
Java:创建、读取或更新 Excel 文档
java·excel
带刺的坐椅3 小时前
Solon v3.4.7, v3.5.6, v3.6.1 发布(国产优秀应用开发框架)
java·spring·solon
四谎真好看5 小时前
Java 黑马程序员学习笔记(进阶篇18)
java·笔记·学习·学习笔记
桦说编程5 小时前
深入解析CompletableFuture源码实现(2)———双源输入
java·后端·源码
java_t_t5 小时前
ZIP工具类
java·zip
lang201509286 小时前
Spring Boot优雅关闭全解析
java·spring boot·后端
pengzhuofan6 小时前
第10章 Maven
java·maven
百锦再7 小时前
Vue Scoped样式混淆问题详解与解决方案
java·前端·javascript·数据库·vue.js·学习·.net
刘一说7 小时前
Spring Boot 启动慢?启动过程深度解析与优化策略
java·spring boot·后端
壹佰大多7 小时前
【spring如何扫描一个路径下被注解修饰的类】
java·后端·spring