mcpField
J
java-junit

java-junit

github.com/github测试与质量40.5k11.7k 次安装1 天前更新
代码仓库

关于 java-junit

面向 Java 开发的测试指导技能,涵盖 JUnit 5/6、AssertJ 和 Mockito。它强调遵循项目现有约定、编写确定性测试,并安全处理测试失败。

主要功能

  1. 01识别现有构建与测试约定
  2. 02JUnit 5 和 6 指导
  3. 03断言与 Mockito 实践
  4. 04确定性测试方法
  5. 05单元与集成测试配置
  6. 06测试安全与验证规则

适用场景

  1. 01为现有 Java 项目添加测试
  2. 02消除不稳定测试中的时间或随机性
  3. 03拆分单元与集成测试运行

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/github/awesome-copilot --skill java-junit

安装后在 Claude Code 中输入/java-junit确认已加载。

附带文件references/assertj-and-mockito.mdreferences/build-setup.md

详细介绍

使用 JUnit 5/6、AssertJ 和 Mockito 进行 Java 测试

不依赖特定框架的指南,助你编写快速、确定性的单元测试。使用 Spring 切片测试时,请用 spring-boot-testing(如果已安装);需要在 Docker 中使用真实数据库或消息代理时,请用 java-testcontainers;遇到无法解释的故障时,请用 java-debugging。

首先:检测现状,不要强加选择

  1. 阅读 pom.xml/build.gradle*:JUnit 版本(junit-jupiter、junit-bom,或从 Spring Boot BOM 继承)、断言库、Mockito、Surefire/Failsafe 版本以及 Java 发布版本。
  2. 沿用 src/test/java 中已有的约定(命名、断言库、静态导入、模拟风格)。如果项目尚未使用 AssertJ、Mockito 或 JaCoCo,未经询问不要引入。
  3. 切勿隐式升级 JUnit 主版本;升级应作为单独任务处理(如果已安装,请参阅 java-upgrade)。

JUnit 5 与 JUnit 6

JUnit 5(最新版本为 5.14.x)JUnit 6(已发布 6.0;当前版本为 6.1.x)
Java 基线版本817(已在发布的 Gradle 模块元数据中核实)
版本编号Platform 为 1.x,Jupiter 为 5.x,Vintage 为 5.xPlatform、Jupiter 和 Vintage 共用一个版本号
APIorg.junit.jupiter.api.*包名相同;本技能中的 Jupiter 测试在 5.14.4 和 6.0.3 上均可直接编译并通过
6.0 中移除的内容MethodOrderer.Alphanumeric、已弃用的双参数 InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext) 重载(三参数版本仍保留)、junit.jupiter.tempdir.scope、@CsvFileSource(lineSeparator)
CSVunivocity-parsersFastCSV:解析更严格(结束引号后不能有其他字符);表头字段选项现在也适用于表头
其他junit-jupiter-migrationsupport 已弃用;无效的枚举式配置值现在会导致发现失败;@Nested 类的顺序确定但不直观

来源:JUnit 6.0.0 发布说明(https://docs.junit.org/6.0.0/release-notes.html)。请阅读目标版本的说明(https://docs.junit.org/current/release-notes/),并优先以其为准。JUnit 4 测试需要 Vintage 引擎;不要在同一个类中混用 org.junit.Test 和 org.junit.jupiter.api.Test。

依赖(JUnit 5 和 6 相同;已使用 Maven 和 Gradle 验证):导入 org.junit:junit-bom,然后声明 org.junit.jupiter:junit-jupiter(聚合了 api、params、engine),并将作用域设为 test。Gradle 9 还要求添加 testRuntimeOnly("org.junit.platform:junit-platform-launcher")(已验证:若缺少此项,测试执行器会因 "Failed to load JUnit Platform" 而失败),并设置 tasks.test { useJUnitPlatform() }。Maven 需要 Surefire 3.x(已使用 3.6.0 验证)。

断言

遵循项目使用的库。使用纯 Jupiter 时,规则如下:期望值放在第一个参数;消息使用延迟计算的 Supplier;使用 assertAll、assertThrowsExactly 和超时断言。(独立的 instructions/java-junit5-assertions.instructions.md 资源中有更完整的说明,但本技能不会安装该资源。)如果项目使用 AssertJ,集合、字符串和异常优先使用它;相关模式(软断言、assertThatThrownBy、extracting、containsExactly、usingRecursiveComparison)见 references/assertj-and-mockito.md。

  • 断言结果和状态,而不是内部方法被调用的次数。
  • 比较值;避免单独使用 assertNotNull。
  • 切勿捕获 AssertionError/Exception 来让测试通过。

Mock(Mockito)

  • Mock 跨边界的协作者(仓储、HTTP 客户端、时钟、消息发送器)。不要 mock 值对象、记录类、集合、String 或被测类;应使用真实实例或简单的伪对象。
  • 如果交互具有状态,优先使用手写伪对象,而不是 mock。
  • 使用 @ExtendWith(MockitoExtension.class),并搭配 @Mock/@InjectMocks/@Captor。此处默认启用严格存根,因此未使用的存根会导致测试失败(UnnecessaryStubbingException)。请修正测试;只有在共享设置确有理由时,才使用 @MockitoSettings(strictness = Strictness.LENIENT) 放宽限制。
  • Mockito 5 默认使用内联 mock maker。在 JDK 21+ 上,它可能会自行附加并打印动态 Agent 警告。对于 Mockito 5.14.0+,应改为将 mockito-core 注册为 -javaagent(Maven 和 Gradle 的配置见 references/assertj-and-mockito.md,已在 JDK 21 和 25 上验证)。请先检查实际解析的版本:较早的 5.x JAR 缺少 Premain-Class,不能用作 Agent。升级前请先征求同意;否则请使用已安装版本对应的文档中所述的插桩配置。
  • Mockito 5 要求 Java 11+。其默认内联 mock maker 不适用于 GraalVM 原生镜像,此时应使用子类 mock maker(Mockito 5.0.0 发行说明:https://github.com/mockito/mockito/releases/tag/v5.0.0)。
  • 避免使用 mockStatic/mockConstruction;应在静态调用外封装一个接口。

确定性

  • 时间:注入 java.time.Clock(Clock.fixed(...)),并调用 Instant.now(clock);避免在被测代码中使用 Instant.now()/LocalDate.now()。
  • 随机性:注入使用固定种子的 Random/RandomGenerator;如果生成了种子,请记录该种子。
  • 不要依赖默认区域设置、时区、文件编码、网络或墙上时钟休眠。请显式设置它们(较新的 6.x 版本增加了内置的区域设置/时区/系统属性扩展;请检查对应版本的发行说明,否则使用 try/finally)。

单元测试与集成测试

单元测试(*Test)集成测试(*IT)
MavenSurefire,mvn testFailsafe,mvn verify
Gradletest 任务单独的 integrationTest 任务(JVM Test Suite),并接入 check
速度毫秒级,无 I/O可能使用 Docker/DB

Surefire 默认匹配 *Test、Test*、*Tests、*TestCase;Failsafe 匹配 *IT、IT*、*ITCase。Failsafe 需要绑定 integration-test 和 verify 目标,并通过 mvn verify 运行,而不是 mvn test。也可以通过 @Tag 拆分。数据库和消息代理请参阅 java-testcontainers;Spring 切片请参阅 spring-boot-testing。完整构建代码片段见 references/build-setup.md。

覆盖率与变异测试(可选)

  • JaCoCo:仅在项目已使用或用户提出要求时添加。与 Surefire/Failsafe 搭配使用时,应使用 <argLine>@{argLine} ...</argLine>,以免覆盖 JaCoCo Agent。
  • 覆盖率是用于发现异味的指标,而非目标;绝不要为了提高数值而添加没有断言的测试,也不要添加项目尚未采用的覆盖率门槛。
  • PIT(变异测试)速度较慢;仅在项目已使用或用户提出要求时,针对变更的类运行(参见 references/build-setup.md,其中记录了已验证的 pitest-maven + JUnit 5 插件运行情况)。

Agent 护栏

  1. 绝不为了让测试通过而删除、注释掉、添加 @Disabled、削弱(放宽断言、扩大容差、吞掉异常)或跳过失败的测试。查明原因。
  2. 判断是测试还是生产代码有误。如果修复会改变生产行为,请先停下并询问用户;如果测试表达的预期显然已过时,请说明这一点并提出修改建议。
  3. 不要添加 -DskipTests、-Dmaven.test.skip、-x test 或 failIfNoTests=false 来让构建通过。
  4. 不要模拟被测类,也不要断言模拟对象的内部状态来“证明”正确性。
  5. 先运行范围最小的测试,再运行完整构建:
    • Maven:mvn -q -Dtest=OrdersTest test(单个方法:-Dtest='OrdersTest#place_should_saveAndNotify_when_itemValid'),然后运行 mvn verify。
    • Gradle:./gradlew test --tests 'demo.OrdersTest',然后运行 ./gradlew check。 如果存在项目包装器,请优先使用(./mvnw、./gradlew)。
  6. 对于不稳定的测试:通过重复运行来复现,然后消除非确定性因素(时间、顺序、共享状态、异步等待);不要添加重试。
  7. 新代码应在现有测试旁边添加新测试,并保持相同风格:正常路径、边界情况、错误情况。

参考资料

  • references/assertj-and-mockito.md:AssertJ 模式、Mockito 严格性/参数捕获器/Agent 设置,以及何时不应使用模拟。
  • references/build-setup.md:JUnit 5/6、Failsafe 拆分、JaCoCo、PIT 的 Maven 和 Gradle(Kotlin DSL)设置。

评论

支持 Markdown