单元测试与JUnit

单元测试与JUnit

2026年5月16日·#javawebai/后端基础Java/Maven/JUnit·934 字 5 分钟
浏览量加载中...
AI 摘要- DeepSeek

软件测试阶段划分、测试方法分类、JUnit单元测试入门、断言、常用注解及依赖范围

JUnit单元测试#

测试概述#

测试是一种用来促进鉴定软件正确性、完整性、安全性和质量的过程。

测试阶段划分#

测试阶段划分

阶段说明目的测试人员
单元测试对软件最小组成单位进行测试检验基本组成单位的正确性开发人员
集成测试将通过测试的单元组合后测试检查单元之间的协作是否正确开发人员
系统测试对集成好的软件系统进行彻底测试验证正确性、性能是否满足要求测试人员
验收测试针对用户需求、业务流程的正式测试验证是否满足验收标准客户/需求方

测试方法#

测试方法

方法说明
白盒测试清楚软件内部结构和代码逻辑,用于验证代码和逻辑正确性
黑盒测试不清楚内部结构,用于验证功能、兼容性、验收测试
灰盒测试结合白盒和黑盒,既关注内部结构又考虑外部表现

灰盒测试

JUnit 单元测试#

JUnit 是最流行的 Java 测试框架之一。相比在 main 方法中测试,JUnit 具有以下优势:

JUnit优势

main 方法测试的问题JUnit 的优势
测试代码与源代码未分开,难维护测试代码与源代码分离,便于维护
一个方法测试失败影响后面方法各测试方法独立运行
无法自动化测试,得不到测试报告可自动化测试,自动产出测试报告

入门示例#

引入依赖(pom.xml):

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>

编写测试类(src/test/java 目录下):

@Test
public void testGetAge() {
Integer age = new UserService().getAge("110002200505091218");
System.out.println(age);
}
  • 测试通过:显示绿色
  • 测试失败:显示红色

命名规范:

  • 测试类命名:XxxTest
  • 测试方法命名:public void xxx() { ... }

断言#

JUnit 提供断言方法,验证被测试方法是否按预期工作。

@Test
public void testGetAge() {
Integer age = new UserService().getAge("110002200505091218");
Assertions.assertNotEquals(18, age, "两个值相等");
}
@Test
public void testGetGender() {
String gender = new UserService().getGender("612429198904201611");
Assertions.assertEquals("男", gender);
}

断言测试结果

常见注解#

注解说明
@Test标记方法为测试方法
@BeforeEach每个测试方法执行前运行
@AfterEach每个测试方法执行后运行
@BeforeAll所有测试方法执行前运行一次(必须 static)
@AfterAll所有测试方法执行后运行一次(必须 static)
@DisplayName指定测试类或方法的显示名称
@ParameterizedTest标记为参数化测试方法
@ValueSource为参数化测试提供数据源

生命周期注解示例:

public class UserServiceTest {
@BeforeEach
public void testBefore() {
System.out.println("before...");
}
@AfterEach
public void testAfter() {
System.out.println("after...");
}
@BeforeAll
public static void testBeforeAll() {
System.out.println("before all ...");
}
@AfterAll
public static void testAfterAll() {
System.out.println("after all...");
}
@Test
public void testGetAge() {
Integer age = new UserService().getAge("110002200505091218");
System.out.println(age);
}
}

注解输出结果

参数化测试示例:

@DisplayName("测试-学生业务操作")
public class UserServiceTest {
@DisplayName("测试-获取年龄")
@Test
public void testGetAge() {
Integer age = new UserService().getAge("110002200505091218");
System.out.println(age);
}
@DisplayName("测试-获取性别")
@ParameterizedTest
@ValueSource(strings = {"612429198904201611", "612429198904201631", "612429198904201626"})
public void testGetGender(String idcard) {
String gender = new UserService().getGender(idcard);
System.out.println(gender);
}
}

参数化测试输出

依赖范围#

通过 <scope> 标签控制依赖的使用范围:

依赖范围

scope 值主程序(main)测试程序(test)打包(package)
compile(默认)✅✅✅
test❌✅❌
provided✅✅❌
runtime❌✅✅

典型用法:JUnit 依赖设置 scope 为 test,表示该依赖仅测试程序可用,主程序中无法使用。

<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.1</version>
<scope>test</scope>
</dependency>

scope配置

注意事项#

  • 单元测试代码应放在 src/test/java 目录下,与源代码分离。
  • @BeforeAll 和 @AfterAll 方法必须使用 static 修饰。
  • 依赖范围合理设置可避免将测试依赖打入生产包。

评论区

[ 标签 ]
# AI37# AI 编程2# AI工具1# AI绘图1# AI辅助开发2# Ajax7# Apifox1# AstrBot3# Astro2# CC Switch1# CDN2# Claude Code1# claudecode2# ClaudeCode1# Cloudflare2# CloudFlare2# CloudFlare-ImgBed3# coc4# CSS10# DeepSeek6# deepseek2# DELETE1# Docker5# EdgeOne3# Gist1# git1# GitHub1# hexo-circle-of-friends1# HTML9# HTTP10# ImageManager1# Java23# java13# JavaScript11# JavaWeb113# JDBC7# JSON2# JUnit1# LangChain25# Linux4# Logback1# Maven17# Muse Spark1# Mybatis1# MyBatis18# MySQL45# MySql1# NapCat1# Node.js1# obsidian2# Obsidian5# OpenCode4# ORM1# PathVariable1# PicGo1# PyCharm1# Python70# RequestBody1# RequestMapping1# RESTful风格1# skills1# Slf4j1# SpringBoot37# SpringMVC5# SQL2# Streamlit5# Svelte2# TailwindCSS1# Telegram3# Tlias2# Vercel1# vscode2# Vue20# Waline3# Web3# WebDAV1# Web基础6# Web开发6# WinSCP1# YAML1# 三层架构1# 中二宣言1# 书籍1# 使用文档10# 写作1# 函数2# 刷步数1# 前端52# 动态1# 动漫1# 包1# 单词2# 博客8# 博客工作流1# 博客开发2# 参数接收1# 友链1# 反思2# 后端48# 图床6# 地图1# 备份2# 大模型1# 奇思妙想1# 存储1# 学习方法6# 学校1# 宝塔面板3# 宝宝10# 实战4# 对象1# 导航栏1# 工具2# 布局2# 开发1# 开发工具1# 开发规范1# 开心1# 异常处理1# 影视2# 微信1# 性能优化2# 总结1# 想法15# 感受1# 感悟11# 指南1# 提示词工程2# 插件5# 故障排除1# 效率工具2# 教程10# 数据分析9# 数据库27# 数据结构1# 文件操作2# 斩神1# 日常95# 日志框架1# 朋友圈1# 朱元璋1# 模块1# 模板1# 正则表达式2# 测试3# 游戏2# 爬虫7# 生活迁移1# 电影2# 电脑1# 碎碎念1# 视觉识别1# 类1# 类型注解1# 网络基础2# 网络教室1# 羊毛2# 脚本2# 脚本工具1# 自动化2# 蓝奏云1# 表单1# 订阅推荐2# 记录2# 评论系统1# 词根1# 词缀1# 说说1# 足迹1# 跑步2# 路径参数1# 转载2# 运动1# 部署11# 部落冲突1# 配置1# 随机图1# 面向对象5# 音乐3# 音标1# 项目实战11# 饮食1# 驼峰命名1# 高德地图1
[ 公告 ]

如果你喜欢,那么欢迎来到我的世界!

了解更多
[ 音乐 ]
封面

音乐

暂未播放

0:000:00
暂无歌词
找不到相关结果。
[ contents ]
[ 全部文章 ]