increment-code-unit-test-creat

v1.0.0

Use when generating JUnit 5 + Mockito unit tests for Java/Maven source code, especially for incremental changes on a git branch. Activates when user asks to...

1· 89·0 current·0 all-time

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for endcy/increment-code-unit-test-creat.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "increment-code-unit-test-creat" (endcy/increment-code-unit-test-creat) from ClawHub.
Skill page: https://clawhub.ai/endcy/increment-code-unit-test-creat
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install increment-code-unit-test-creat

ClawHub CLI

Package manager switcher

npx clawhub@latest install increment-code-unit-test-creat
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
The name/description, README, and SKILL.md consistently describe generating JUnit 5 + Mockito tests for Maven Java projects and operating incrementally against Git diffs. The requested tools (Git and Maven) and the file reads/writes (pom.xml, src/main/java, src/test/java) align with that purpose; there are no unrelated binaries or credentials required.
Instruction Scope
The instructions remain within the stated scope: they read source code and pom.xml, run git diffs, generate test classes, may edit pom.xml to add test dependencies upon user confirmation, and run Maven lifecycle goals (test-compile, test, jacoco). This is expected for an automated test-generator, but it does mean the agent will modify repository files and execute build/test commands in the user's environment (which can run arbitrary build plugins or scripts). Users should be aware of these side effects and review/approve changes before committing.
Install Mechanism
Instruction-only skill with no install spec or external downloads. No code is written to disk by an installer. The runtime relies on existing Git and Maven binaries on the host, which is appropriate.
Credentials
The skill declares no environment variables or credentials and does not request unrelated secrets. It reads local repository files and may write changes to pom.xml / add generated test files — those accesses are proportional to the task.
Persistence & Privilege
The skill is not always-enabled and does not persist itself into agent config. However, it does instruct modifying the project's pom.xml and writing generated test files, and will invoke Maven (which can execute build plugins). These are normal for the skill's function but are file-system and execution privileges the user should permit explicitly.
Assessment
This skill appears coherent for automatically generating JUnit5+Mockito tests for a Maven Java project and does not request unrelated credentials. Before using it: 1) Run it on a feature branch or backup your repo (it may modify pom.xml and add/overwrite test files). 2) Review any proposed pom.xml edits before applying them. 3) Be aware that running 'mvn test' or other build goals can execute build plugins or scripts in your project — run in an isolated/CI environment if you are unsure. 4) Inspect generated tests for correctness and for any accidental tight coupling to production data/config. If you want extra safety, ask the skill to only produce test code as output (no automatic file writes) and manually apply changes after review.

Like a lobster shell, security has layers — review code before you run it.

Mockitovk9798rang01gea7g17czcepmn184y0ewjunitvk9798rang01gea7g17czcepmn184y0ewlatestvk9798rang01gea7g17czcepmn184y0ew
89downloads
1stars
1versions
Updated 1w ago
v1.0.0
MIT-0

Increment Code Unit Test Creator - 增量代码单元测试生成器

为 Java/Maven 项目生成 JUnit 5 + Mockito 单元测试,覆盖增量代码变更,目标覆盖率 90%~100%

核心特性

增量代码感知:

  • 自动检测 Git 仓库,对比 main(或 master)分支获取增量变更
  • 精准定位新增/修改的方法、字段、类
  • 仅针对变更部分生成或补充测试,不重复已有覆盖

全量测试生成:

  • 指定类或包路径时,若对应测试类不存在则全量生成
  • 目标覆盖率 90%~100%,确保方法级别覆盖

全 Mock 策略:

  • 所有外部依赖(数据库、Redis、HTTP 调用、消息队列等)使用 Mockito 模拟
  • 不编写集成测试,避免数据依赖导致的不稳定性

源码深度读取:

  • 生成测试前读取依赖的方法、类、对象定义
  • 构造真实对象时传入有意义的属性值,不使用空对象

仅测源码:

  • 绝不针对测试类本身生成单元测试
  • 跳过 *Test.java*Spec.java*TestCase.java 等文件

激活条件

当用户提到以下关键词时激活:

  • "生成单元测试"
  • "为这个类写测试"
  • "为增量代码生成测试"
  • "补充单元测试"
  • "代码变更测试"
  • "提高测试覆盖率"
  • "incremental test"
  • "unit test for changed code"
  • "generate tests"

与全项目测试生成的区别:

  • 本 skill 聚焦于增量变更或指定类的精准测试生成
  • 不是全项目批量扫描,而是按需、按需增量覆盖

依赖检查

必需工具

工具用途检查方式
Git获取增量代码差异git --version
Maven解析依赖、运行测试mvn --version

必需测试依赖

在生成测试前,检查项目 pom.xml 是否包含以下依赖:

第一步:检测 JDK 版本

读取 pom.xml 中的 <maven.compiler.source><java.version> 属性,确定目标 JDK 版本:

JDK 版本junit-jupitermockito-coremockito-junit-jupiter
Java 85.9.x4.11.04.11.0
Java 11+5.9.x5.5.05.5.0

重要: Mockito 5.x 编译后的 class 文件版本为 55.0 (Java 11+),在 Java 8 项目中使用会导致编译失败。必须根据 JDK 版本选择对应的 Mockito 版本。

第二步:检查依赖是否存在

依赖版本(按 JDK)作用域
org.junit.jupiter:junit-jupiterJava 8→5.9.3 / Java 11+→5.9.3test
org.mockito:mockito-coreJava 8→4.11.0 / Java 11+→5.5.0test
org.mockito:mockito-junit-jupiterJava 8→4.11.0 / Java 11+→5.5.0test

可选但推荐:

  • org.mockito:mockito-inline — 支持 static/final 方法 mock

缺失处理:

  1. 提示用户项目缺少 JUnit 5 / Mockito 依赖
  2. 展示需要添加的 Maven 依赖片段(见 references/dependency-config.md
  3. 询问用户是否自动添加到 pom.xml
  4. 用户确认后自动添加并执行 mvn test-compile 验证

完整工作流程

Step 0: 项目扫描与依赖检查

# 1. 确认是 Maven 项目(存在 pom.xml)
# 2. 检查测试依赖是否存在于 pom.xml
# 3. 确认是 Java 项目(src/main/java 目录存在)

输出: 依赖状态报告(完整 / 缺失需补充)


Step 1: 增量代码分析(Git 仓库模式)

# 1. 确认默认分支(main 优先,不存在则 master)
git rev-parse --verify main 2>/dev/null || git rev-parse --verify master 2>/dev/null

# 2. 获取增量变更(与默认分支对比)
git diff <default-branch> --name-only --diff-filter=ACMR -- '*.java'

# 3. 排除测试文件
# 过滤掉 src/test/java 路径下的文件

# 4. 获取具体方法级变更
git diff <default-branch> -- src/main/java/包路径/类名.java

# 5. 解析变更类型
# - 新增类
# - 新增方法
# - 修改方法
# - 修改字段/依赖

输出: 增量变更清单(类 -> 方法 -> 变更类型)


Step 2: 测试类存在性检查

# 对每个变更的源文件,检查对应测试类是否存在
# 源文件:src/main/java/com/example/service/UserService.java
# 测试文件:src/test/java/com/example/service/UserServiceTest.java

# 规则:
# - 测试类存在且测试方法已覆盖变更方法 -> 跳过
# - 测试类存在但未覆盖变更方法 -> 补充测试方法
# - 测试类不存在 -> 全量生成

Step 3: 源码深度读取

在生成测试前,对目标类执行以下读取:

  1. 读取目标类源码:了解字段、依赖注入、方法签名
  2. 读取依赖类/接口:了解注入依赖的类型和方法签名
  3. 读取依赖方法的实现:了解返回类型、可能的异常
  4. 读取相关 Entity/DTO/VO:构造真实测试对象

构造对象原则:

  • 传入有意义的属性值(非空、非 null、符合业务语义)
  • 使用 Builder / 构造器 / 直接 set,遵循类的构造方式
  • 对枚举、集合等非空字段赋默认值

Lombok 特殊处理(必须检查):

  • 检查目标类是否有 @Setter(AccessLevel.NONE)@Setter(AccessLevel.PROTECTED) 注解
    • 如果字段被禁用 setter:不要尝试反射设置该字段,应检查其 getter 是否为计算型方法
    • 计算型 getter 通常返回多个字段运算后的值(如 electricityAmount.add(serviceAmount)),应设置参与计算的源字段
  • 检查 @Accessors(chain = true) —— 此时 setter 返回自身而非 void,可直接链式调用
  • 检查 @FieldDefaults —— 可能影响字段访问级别

Step 4: 测试生成 / 补充

根据 Step 2 的结果选择策略:

策略 A:全量生成(测试类不存在)

  1. 为类中每个 public 方法生成至少一个测试方法
  2. 覆盖以下场景:
    • 正常路径(Happy Path)
    • 边界条件(null、空集合、空字符串、极值)
    • 异常路径(抛出异常的情况)
    • 分支覆盖(if/else 各分支)
  3. 所有外部依赖使用 @Mock + Mockito 模拟
  4. 使用 @InjectMocks 注入被测实例
  5. 目标覆盖率 90%~100%

策略 B:增量补充(测试类已存在)

  1. 识别增量代码中未被现有测试覆盖的方法
  2. 为每个未覆盖方法生成新测试方法
  3. 不修改已有通过的测试(除非变更破坏了原有逻辑)
  4. 验证新增测试方法与已有测试不冲突

跳过规则(满足任一即跳过):

  • 纯 getter/setter 方法
  • Lombok 注解生成的方法(@Data, @Getter, @Setter
  • toString()equals()hashCode()(除非手动实现且含业务逻辑)
  • 仅包含日志输出的方法
  • 委托方法(直接转发到另一个方法,无额外逻辑)

必须测试(满足任一即生成):

  • 包含条件判断(if/switch)的方法
  • 包含循环遍历的方法
  • 调用外部依赖的方法
  • 包含异常处理(try/catch)的方法
  • 包含数据转换/校验的方法
  • 包含状态变更的方法

Step 5: 测试编译验证

# 1. 编译测试代码
mvn test-compile -q

# 2. 如果编译失败,检查并修复
# - 导入缺失
# - 方法签名不匹配
# - 类型不匹配

# 3. 运行单个测试类验证
mvn test -Dtest=ClassNameTest -q

Step 6: 覆盖率验证(可选)

# 使用 JaCoCo 验证覆盖率
mvn test jacoco:report -q

# 检查覆盖率报告
# target/site/jacoco/index.html

# 目标:方法覆盖率 >= 90%

未达标处理:

  1. 识别未覆盖的方法/分支
  2. 补充对应测试方法
  3. 重新运行覆盖率检查
  4. 重复直到达标

测试生成规则

测试类命名

源类名:UserService.java
测试类名:UserServiceTest.java

源类名:OrderServiceImpl.java
测试类名:OrderServiceImplTest.java

测试方法命名

// 格式:[方法名]_[场景描述]_[期望结果]
@Test
void createOrder_validInput_returnsCreatedOrder() { }

@Test
void createOrder_nullInput_throwsIllegalArgumentException() { }

@Test
void getUser_notFound_returnsEmptyOptional() { }

Mock 策略

@ExtendWith(MockitoExtension.class)
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @Mock
    private EmailService emailService;

    @Mock
    private RedisTemplate<String, Object> redisTemplate;

    @InjectMocks
    private UserService userService;

    // 所有外部依赖都 @Mock,不写真实调用
}

测试方法覆盖清单

对每个被测 public 方法,至少覆盖:

场景优先级
正常输入,正常返回P0
输入为 nullP0
输入为空集合/空字符串P1
依赖抛出异常P1
分支条件各路径P0
边界值(0、-1、MAX)P1
并发/线程安全(如适用)P2

测试模板

详见 references/test-template.md

核心结构

package com.example.service;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.BeforeEach;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
@DisplayName("UserService 单元测试")
class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserService userService;

    @BeforeEach
    void setUp() {
        // 通用 mock 设置(如有)
    }

    @Test
    @DisplayName("创建用户 - 正常路径")
    void createUser_validInput_returnsUser() {
        // Given
        UserDTO dto = new UserDTO();
        dto.setName("test");
        dto.setEmail("test@example.com");
        when(userRepository.save(any(User.class))).thenReturn(new User("test"));

        // When
        User result = userService.createUser(dto);

        // Then
        assertNotNull(result);
        assertEquals("test", result.getName());
        verify(userRepository).save(any(User.class));
    }
}

常见问题排查

Getter 返回 null0,但字段已设置

症状: 测试中通过 setField(value) 设置了值,但 obj.getField() 返回 null 或默认值。

排查步骤:

  1. 检查该 getter 是否为 Lombok 自动生成(简单返回字段值)还是 手动实现的计算型方法
  2. 检查字段是否有 @Setter(AccessLevel.NONE) —— 如果有,getter 很可能也是计算型的
  3. 读取 getter 的实现,找到它实际计算的源字段
  4. 设置参与计算的源字段而非目标字段

示例:

// 实际代码中:
// @Setter(AccessLevel.NONE)
// private BigDecimal chargeMoneyAmount;
// public BigDecimal getChargeMoneyAmount() {
//     return electricityAmount.add(serviceAmount);  // 计算型 getter
// }

// ❌ 错误:设置目标字段无效,因为 getter 不读它
field.set(order, BigDecimal.valueOf(6.0));

// ✅ 正确:设置参与计算的源字段
order.setElectricityAmount(BigDecimal.valueOf(6.0));
order.setServiceAmount(BigDecimal.ZERO);

any() 匹配器导致 NullPointerException

症状: when(mock.method(any(SomeClass.class))).thenReturn(...) 在 stub 注册阶段抛出 NPE。

原因: 某些接口(特别是外部模块的接口)的方法在接收 null 参数时会直接抛出异常,而 any() 在 stub 注册阶段会先以 null 参数试探性调用。

解决: 使用 doReturn() + nullable(Class) 匹配器:

doReturn(result).when(mockService).method(
    ArgumentMatchers.<SomeClass>nullable(SomeClass.class)
);

Stubbing 参数数量不匹配

症状: PotentialStubbingProblem 异常,提示实际调用的参数数量与 stub 不一致。

解决:

  • 确保 mock 的 when() 参数数量与实际调用一致
  • 对于可能有多参数重载的方法,使用 nullable() 匹配器覆盖所有参数

@MockitoSettings(LENIENT) vs lenient().when()

原则: 优先使用 lenient().when() 针对个别 stub,避免全局 LENIENT

// ✅ 推荐:仅对特定 stub 放宽
lenient().when(redisUtils.set(anyString(), any())).thenReturn(true);

// ⚠️ 谨慎使用:全局 lenient 会隐藏其他 stubbing 问题
@MockitoSettings(strictness = Strictness.LENIENT)

只有当多个 stub 存在参数数量/类型差异且难以精确匹配时,才使用全局 LENIENT


错误处理

pom.xml 找不到

问题:项目中不存在 pom.xml

解决:
1. 确认当前目录是否为 Maven 项目根目录
2. 如果是子模块,找到对应的 pom.xml
3. 如果确实不是 Maven 项目,提示用户本 skill 仅支持 Java/Maven

Git 仓库不存在

问题:当前目录不是 Git 仓库

解决:
1. 如果用户指定了具体类/包路径,跳过增量分析,直接全量生成
2. 如果用户要求"增量测试"但无 Git,提示用户初始化 git 仓库

main 和 master 分支都不存在

问题:git rev-parse --verify main 和 master 都失败

解决:
1. 列出所有远程分支:git branch -r
2. 询问用户应对比哪个分支
3. 或使用 git diff HEAD~1 作为替代(最近一次提交)

测试编译失败

问题:mvn test-compile 失败

解决:
1. 检查生成的测试代码导入是否正确
2. 检查方法签名是否与源类匹配
3. 检查 Mockito when/thenReturn 的返回类型
4. 修复后重新编译

覆盖率未达标

问题:JaCoCo 报告显示覆盖率低于 90%

解决:
1. 读取 JaCoCo 报告,识别未覆盖的方法/分支
2. 为每个未覆盖点生成补充测试
3. 重新运行覆盖率检查
4. 若仍有无法覆盖的分支(如防御性代码),在报告中说明原因

依赖类/方法不存在

问题:源码引用的依赖类在类路径中找不到

解决:
1. 检查是否为外部依赖(需 mvn dependency:resolve)
2. 检查是否为同项目其他模块(需先编译依赖模块)
3. 对找不到的依赖,使用 mock 占位,在测试注释中说明

使用示例

示例 1:为指定类生成全量单元测试

用户:为 UserService 生成单元测试

AI: 收到!开始执行单元测试生成流程:

Step 0: 项目扫描...
  ✅ Maven 项目确认
  ✅ JUnit 5 + Mockito 依赖存在

Step 1: 目标类分析...
  📄 com.example.service.UserService (120 行, 8 个 public 方法)

Step 2: 测试类存在性检查...
  ❌ UserServiceTest.java 不存在 -> 全量生成

Step 3: 源码深度读取...
  📖 UserService.java - 8 个 public 方法
  📖 UserRepository.java - 依赖接口
  📖 User.java - Entity 定义
  📖 UserDTO.java - 参数对象

Step 4: 全量测试生成...
  ✅ 生成 12 个测试方法(覆盖 8 个 public 方法)
  📝 UserServiceTest.java (350 行)

Step 5: 编译验证...
  ✅ mvn test-compile 通过
  ✅ mvn test -Dtest=UserServiceTest 通过(12/12 passed)

Step 6: 覆盖率验证...
  ✅ 方法覆盖率:95%(19/20 方法已覆盖)
  ✅ 分支覆盖率:88%

✅ 完成!测试类已生成:src/test/java/com/example/service/UserServiceTest.java

示例 2:增量代码测试补充

用户:为这次的增量代码生成单元测试

AI: 收到!开始执行增量测试流程:

Step 0: 项目扫描...
  ✅ Maven 项目确认
  ✅ 测试依赖存在

Step 1: 增量代码分析(对比 main 分支)...
  📊 发现 3 个变更文件:
    - UserService.java (+2 个方法)
    - OrderController.java (修改 1 个方法)
    - PaymentHelper.java (新增类)

Step 2: 测试类存在性检查...
  ✅ UserServiceTest.java 存在 -> 检查覆盖
  ✅ OrderControllerTest.java 存在 -> 检查覆盖
  ❌ PaymentHelperTest.java 不存在 -> 全量生成

Step 3: 增量方法覆盖分析...
  UserServiceTest:
    ❌ verifyEmail() - 未覆盖 -> 补充
    ❌ batchUpdate() - 未覆盖 -> 补充
  OrderControllerTest:
    ❌ updateOrderStatus() - 已修改,现有测试不覆盖新逻辑 -> 补充
  PaymentHelperTest:
    -> 全量生成(5 个 public 方法)

Step 4: 测试生成...
  ✅ UserServiceTest.java 补充 2 个测试方法
  ✅ OrderControllerTest.java 补充 1 个测试方法
  ✅ PaymentHelperTest.java 全量生成 8 个测试方法

Step 5: 编译验证...
  ✅ 全部通过

Step 6: 覆盖率验证...
  ✅ 变更方法覆盖率:100%

✅ 完成!共补充/生成 11 个测试方法

示例 3:缺少测试依赖

用户:为 OrderService 生成单元测试

AI: 收到!开始执行单元测试生成流程:

Step 0: 项目扫描...
  ✅ Maven 项目确认
  ❌ 缺少 JUnit 5 依赖
  ❌ 缺少 Mockito 依赖

⚠️ 检测到项目缺少单元测试必需依赖:

需要在 pom.xml 中添加以下依赖:
<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.9.3</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>5.5.0</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-junit-jupiter</artifactId>
        <version>5.5.0</version>
        <scope>test</scope>
    </dependency>
</dependencies>

是否自动添加到 pom.xml?(y/n)

用户:y

AI: ✅ 依赖已添加到 pom.xml
    ✅ mvn test-compile 验证通过

继续生成 OrderService 单元测试...

配置项

Maven Surefire 插件配置

为确保 JUnit 5 正确运行,检查 pom.xml 中是否配置了 Surefire 插件:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.1.2</version>
        </plugin>
    </plugins>
</build>

JaCoCo 覆盖率插件(可选)

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

版本

版本日期作者变更
1.0.02026-04-15endcy初始版本,支持 JUnit 5 + Mockito 增量/全量单元测试生成

Comments

Loading comments...