当前位置: 首页 > news >正文

JUnit5 实操

1.JUnit 的导入

<dependencies><!-- JUnit Jupiter API + Engine --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.10.0</version><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.10.0</version><scope>test</scope></dependency>
</dependencies>

2.常用注解

注解

作用

@Test

声明一个测试方法

@BeforeEach

每个测试方法执行前执行

@AfterEach

每个测试方法执行后执行

@BeforeAll

所有测试开始前执行(需 static

@AfterAll

所有测试结束后执行(需 static

@DisplayName("xxx")

给测试类或方法自定义名称

@Disabled

禁用该测试方法

@Tag("xxx")

添加标签(分组执行测试用)

3.常用断言

Assertions.assertEquals(expected, actual); // 相等

Assertions.assertNotEquals(a, b); // 不相等

Assertions.assertTrue(expression); // 断言为 true

Assertions.assertFalse(expression); // 断言为 false

Assertions.assertNull(obj); // 是 null

Assertions.assertNotNull(obj); // 不是 null

Assertions.assertThrows(ArithmeticException.class, () -> 1 / 0); // 异常断言

4.参数测试

基本注解:@ParameterizedTest

替代 @Test,并结合不同的数据源注解,比如:

@ValueSource:传入基础类型

@CsvSource:传入多个参数(逗号分隔)

@MethodSource:使用方法提供参数

@EnumSource:枚举测试

@ArgumentsSource:自定义参数源

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.*;import java.util.stream.Stream;import static org.junit.jupiter.api.Assertions.*;// 枚举定义
enum Status {NEW, IN_PROGRESS, DONE
}public class ParameterizedTestExample {// 1. @ValueSource 示例:基础类型参数(int / String / long / double)@ParameterizedTest@ValueSource(strings = {"hello", "junit", "test"})@DisplayName("测试字符串长度为非空")void testWithValueSource(String word) {assertNotNull(word);assertTrue(word.length() > 0);}// 2. @CsvSource 示例:多参数输入@ParameterizedTest@CsvSource({"1, 2, 3","2, 3, 5","5, 7, 12"})@DisplayName("测试加法")void testWithCsvSource(int a, int b, int expectedSum) {assertEquals(expectedSum, a + b);}// 3. @MethodSource 示例:方法提供复杂参数(支持对象)@ParameterizedTest@MethodSource("provideStringsForIsBlank")@DisplayName("测试字符串是否为空白")void testWithMethodSource(String input, boolean expected) {assertEquals(expected, input == null || input.trim().isEmpty());}static Stream<Arguments> provideStringsForIsBlank() {return Stream.of(Arguments.of("   ", true),Arguments.of("", true),Arguments.of(null, true),Arguments.of("abc", false));}// 4. @EnumSource 示例:遍历枚举值@ParameterizedTest@EnumSource(Status.class)@DisplayName("测试所有状态枚举非空")void testWithEnumSource(Status status) {assertNotNull(status);}// 5. @ArgumentsSource 示例:自定义参数提供器@ParameterizedTest@ArgumentsSource(CustomStringProvider.class)@DisplayName("使用自定义参数源")void testWithArgumentsSource(String input) {assertTrue(input.startsWith("arg"));}// 内部类:实现 ArgumentsProvider 接口static class CustomStringProvider implements ArgumentsProvider {@Overridepublic Stream<? extends Arguments> provideArguments(ExtensionContext context) {return Stream.of("arg1", "arg2", "arg3").map(Arguments::of);}}
}

5.实践例子

import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.*;import java.util.Map;
import java.util.stream.Stream;import static org.junit.jupiter.api.Assertions.*;@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@DisplayName("🧪 UserService CRUD 测试")
@Tag("user")
public class UserServiceTest {private UserService userService;@BeforeAllstatic void beforeAll() {System.out.println("🚀 启动 UserService 测试...");}@AfterAllstatic void afterAll() {System.out.println("✅ 所有测试已完成");}@BeforeEachvoid setUp() {userService = new UserService();}@AfterEachvoid tearDown() {System.out.println("--- 单个测试完成 ---");}@Test@DisplayName("创建用户应返回ID并可查")void testCreateAndGetUser() {Long id = userService.createUser("Alice");assertNotNull(id);assertEquals("Alice", userService.getUser(id));}@Test@DisplayName("删除用户成功后不能再获取")void testDeleteUser() {Long id = userService.createUser("Bob");assertTrue(userService.deleteUser(id));assertNull(userService.getUser(id));}@Test@DisplayName("更新用户名称成功")void testUpdateUser() {Long id = userService.createUser("Charlie");boolean updated = userService.updateUser(id, "Charles");assertTrue(updated);assertEquals("Charles", userService.getUser(id));}@Test@DisplayName("获取所有用户")void testListUsers() {userService.createUser("Tom");userService.createUser("Jerry");Map<Long, String> users = userService.listUsers();assertEquals(2, users.size());assertTrue(users.containsValue("Tom"));assertTrue(users.containsValue("Jerry"));}@Test@DisplayName("创建空用户名应抛异常")void testCreateUserWithNullName() {assertThrows(IllegalArgumentException.class, () -> userService.createUser(" "));}// 🔁 参数化测试:@ValueSource@ParameterizedTest@ValueSource(strings = { "Alice", "Bob", "Charlie" })@DisplayName("使用不同名称创建用户")void testCreateWithValueSource(String name) {Long id = userService.createUser(name);assertNotNull(userService.getUser(id));}// 🔁 参数化测试:@CsvSource@ParameterizedTest@CsvSource({"John, Johnny","Lucy, Lucille"})@DisplayName("创建并更新用户名")void testUpdateWithCsvSource(String original, String updated) {Long id = userService.createUser(original);assertTrue(userService.updateUser(id, updated));assertEquals(updated, userService.getUser(id));}// 🔁 参数化测试:@MethodSource@ParameterizedTest@MethodSource("provideUserNames")@DisplayName("使用方法源批量创建用户")void testCreateWithMethodSource(String name) {Long id = userService.createUser(name);assertNotNull(id);assertEquals(name, userService.getUser(id));}static Stream<Arguments> provideUserNames() {return Stream.of(Arguments.of("Lily"),Arguments.of("James"),Arguments.of("Henry"));}// 🔁 参数化测试:@EnumSource@ParameterizedTest@EnumSource(UserService.Role.class)@DisplayName("枚举角色不为空")void testWithEnumSource(UserService.Role role) {assertNotNull(role);}// 🔁 参数化测试:@ArgumentsSource(自定义)@ParameterizedTest@ArgumentsSource(CustomNameProvider.class)@DisplayName("使用自定义名字创建用户")void testWithArgumentsSource(String name) {Long id = userService.createUser(name);assertTrue(userService.getUser(id).startsWith(name.substring(0, 1)));}static class CustomNameProvider implements ArgumentsProvider {@Overridepublic Stream<? extends Arguments> provideArguments(ExtensionContext context) {return Stream.of("Alan", "Amy", "Ann").map(Arguments::of);}}// 🚫 被禁用的测试@Test@Disabled("逻辑尚未实现")void testFindUserByEmail() {fail("该功能尚未开发");}
}
http://www.dtcms.com/a/284895.html

相关文章:

  • 杭州卓健信息科技有限公司 Java 面经
  • CPP学习之list使用及模拟实现
  • 【39】MFC入门到精通——C++ /MFC操作文件行(读取,删除,修改指定行)
  • 闲庭信步使用图像验证平台加速FPGA的开发:第二十一课——高斯下采样后图像还原的FPGA实现
  • 在VsCode上使用开发容器devcontainer
  • 基于MATLAB的极限学习机ELM的数据分类预测方法应用
  • VSCode 配置 C# 开发环境完整教程(附效果截图)
  • 【后端】.NET Core API框架搭建(7) --配置使用Redis
  • java-字符串
  • 东芝2822AM复印机请求维修C449简单操作修复步骤
  • vue3 自定义vant-calendar header/footer/maincontent
  • 【实时Linux实战系列】利用容器化实现实时应用部署
  • 量化环节剖析
  • 鸿蒙Navigation跳转页面白屏
  • 【agent实战】基于 LangGraph 实现 Agentic RAG:原理、实战与创新全解
  • SII9022ACNU-富利威-HDMI芯片
  • stack,queue,priority_queue的模拟实现及常用接口
  • Qt6-学习Cmakelist(翻译官方文档)
  • Pytorch深度学习框架实战教程02:开发环境部署
  • python学智能算法(二十二)|SVM-点与超平面的距离
  • faster-lio仿真环境问题及解决
  • 腾讯云服务上下载docker以及使用Rabbitmq的流程
  • Python网络爬虫——介绍
  • 【unitrix】 6.5 基础整数类型特征(base_int.rs)
  • Redis:哨兵(Sentinel)
  • MySQL的索引操作及底层结构浅析
  • 产品经理如何描述用户故事
  • modelscope ProxyError: HTTPSConnectionPool(host=‘www.modelscope.cn‘, port=443)
  • 作物长势产量预测yyds!遥感数据同化DSSAT模型,区域精准农业就靠它!
  • 27、鸿蒙Harmony Next开发:ArkTS并发(Promise和async/await和多线程并发TaskPool和Worker的使用)