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))
                )
            );
    }
}
相关推荐
Tirzano几秒前
springsession全能序列化方案
java·开发语言
我登哥MVP4 分钟前
【SpringMVC笔记】 - 2 - @RequestMapping
java·spring boot·spring·servlet·tomcat·intellij-idea·springmvc
殷紫川10 分钟前
深度剖析:Java 并发三大量难题 —— 死锁、活锁、饥饿全解
java
云烟成雨TD18 分钟前
Spring AI Alibaba 1.x 系列【14】ReactAgent 工具执行异常处理
java·人工智能·spring
凯尔萨厮22 分钟前
创建Web多模块项目(Maven管理)
java·maven
香香甜甜的辣椒炒肉29 分钟前
Spring JDBC 万能模板
java·后端·spring
liaowenxiong32 分钟前
实现类和接口的关系
java
编程迪34 分钟前
基于Java和uniapp开发的名片交换分享系统企业名片管理软件个人电子名片小程序源码
java·uni-app·电子名片·名片小程序·名片软件源码
开开心心就好36 分钟前
经典塔防游戏移植移动端随时畅玩
java·前端·科技·游戏·edge·django·pdf
ZPC82101 小时前
moveit servo 发指令给real arm
java·前端·数据库