@shirayner/ace 0.1.0-snapshot.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/bin/ace.js +39 -0
  2. package/package.json +42 -0
  3. package/src/commands/doctor.js +86 -0
  4. package/src/commands/init.js +98 -0
  5. package/src/commands/list.js +67 -0
  6. package/src/core/constants.js +106 -0
  7. package/src/core/installer.js +206 -0
  8. package/src/core/merger.js +103 -0
  9. package/templates/CLAUDE.md +16 -0
  10. package/templates/commands/report.md +63 -0
  11. package/templates/hookify/hookify.block-dangerous-ops.local.md +16 -0
  12. package/templates/hookify/hookify.protect-secrets.local.md +17 -0
  13. package/templates/hookify/hookify.require-verification.local.md +13 -0
  14. package/templates/hooks/java-compile-check.sh +106 -0
  15. package/templates/memory/MEMORY.md +4 -0
  16. package/templates/memory/roles/backend.md +11 -0
  17. package/templates/memory/roles/client.md +11 -0
  18. package/templates/memory/roles/frontend.md +11 -0
  19. package/templates/memory/roles/fullstack.md +11 -0
  20. package/templates/rules/clean-code.md +33 -0
  21. package/templates/rules/code-quality.md +74 -0
  22. package/templates/rules/context-hygiene.md +29 -0
  23. package/templates/rules/memory-policy.md +30 -0
  24. package/templates/rules/reporting.md +9 -0
  25. package/templates/rules/task-recovery.md +13 -0
  26. package/templates/rules/thinking.md +19 -0
  27. package/templates/settings.json +11 -0
  28. package/templates/skills/auto-goal/SKILL.md +188 -0
  29. package/templates/skills/coding/SKILL.md +251 -0
  30. package/templates/skills/coding/references/code-review-guide.md +137 -0
  31. package/templates/skills/coding/references/code-smells.md +201 -0
  32. package/templates/skills/coding/references/implement-guide.md +123 -0
  33. package/templates/skills/coding/references/unit-test-guide.md +211 -0
  34. package/templates/skills/skill-creator/LICENSE.txt +202 -0
  35. package/templates/skills/skill-creator/SKILL.md +479 -0
  36. package/templates/skills/skill-creator/agents/analyzer.md +274 -0
  37. package/templates/skills/skill-creator/agents/comparator.md +202 -0
  38. package/templates/skills/skill-creator/agents/grader.md +223 -0
  39. package/templates/skills/skill-creator/assets/eval_review.html +146 -0
  40. package/templates/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  41. package/templates/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  42. package/templates/skills/skill-creator/references/schemas.md +430 -0
  43. package/templates/skills/skill-creator/scripts/__init__.py +0 -0
  44. package/templates/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  45. package/templates/skills/skill-creator/scripts/generate_report.py +326 -0
  46. package/templates/skills/skill-creator/scripts/improve_description.py +248 -0
  47. package/templates/skills/skill-creator/scripts/package_skill.py +136 -0
  48. package/templates/skills/skill-creator/scripts/quick_validate.py +103 -0
  49. package/templates/skills/skill-creator/scripts/run_eval.py +310 -0
  50. package/templates/skills/skill-creator/scripts/run_loop.py +332 -0
  51. package/templates/skills/skill-creator/scripts/utils.py +47 -0
  52. package/templates/skills/skill-optimize/SKILL.md +287 -0
  53. package/templates/skills/skill-optimize/references/.claude/settings.local.json +7 -0
  54. package/templates/skills/skill-optimize/references/anthropic-design-philosophy.md +250 -0
  55. package/templates/skills/skill-optimize/references/auto-goal-optimization-directions.md +130 -0
  56. package/templates/skills/skill-optimize/references/cross-disciplinary-insights.md +211 -0
  57. package/templates/skills/skill-optimize/references/quality-checklist.md +170 -0
  58. package/templates/skills/skill-optimize/references/theory-foundations.md +201 -0
@@ -0,0 +1,201 @@
1
+ # 代码坏味道详细清单
2
+
3
+ 本文档作为 code-review skill 的参考材料,提供具体的坏味道检查清单。
4
+
5
+ ## Bug风险类
6
+
7
+ ### 空指针/空引用
8
+ - 未判空的变量直接调用方法
9
+ - 集合操作前未检查null或空
10
+ - 链式调用中可能的中断点(`a.b.c.d`)
11
+ - 自动解装箱导致的NPE(`Integer` vs `int`)
12
+
13
+ ### 资源泄漏
14
+ - 文件流未关闭(未使用try-with-resources)
15
+ - 数据库连接未释放
16
+ - 网络连接未正确关闭
17
+ - 锁未释放(ReentrantLock的lock/unlock不匹配)
18
+
19
+ ### 并发问题
20
+ - 共享变量缺少同步
21
+ - 竞态条件(检查-执行模式)
22
+ - 线程不安全类的共享使用(SimpleDateFormat、HashMap在并发环境)
23
+ - 死锁风险
24
+
25
+ ### 异常处理
26
+ - 空catch块(吞异常)
27
+ - 捕获Exception/Throwable过于宽泛
28
+ - 异常被吞掉或只打印日志未处理
29
+ - 在finally中抛出异常覆盖原始异常
30
+
31
+ ### 边界条件
32
+ - 数组/集合越界(索引从0开始还是1开始)
33
+ - 除零风险
34
+ - 整数溢出
35
+ - 字符串截断导致乱码
36
+ - 时间边界(跨天、跨月、跨年)
37
+
38
+ ### 逻辑错误
39
+ - `==` vs `equals`(引用相等 vs 值相等)
40
+ - 短路逻辑误用(`&&` vs `&`)
41
+ - 运算符优先级错误
42
+ - 死代码(不可能到达的条件)
43
+ - 赋值误用为比较(`=` vs `==`)
44
+
45
+ ## 代码坏味道类
46
+
47
+ ### 过长方法 (Long Method)
48
+ - 方法超过50行
49
+ - 方法做了多件事情(多种职责)
50
+ - 需要注释来解释代码块的功能
51
+
52
+ ### 过大类 (Large Class)
53
+ - 类字段/方法数量过多
54
+ - 类承担了过多职责
55
+ - 导入过多(import地狱)
56
+
57
+ ### 重复代码 (Duplicated Code)
58
+ - copy-paste的代码块
59
+ - 相似的逻辑未抽取(仅变量名不同)
60
+ - 结构重复(if/else中的重复代码)
61
+
62
+ ### 过长参数列表 (Long Parameter List)
63
+ - 超过4个参数
64
+ - 参数经常一起出现(应考虑封装为对象)
65
+ - 布尔标志参数(表示方法做多件事)
66
+
67
+ ### 数据泥团 (Data Clumps)
68
+ - 总是一起出现的数据字段
69
+ - 总是一起传递的参数组
70
+ - 总是一起使用的变量
71
+
72
+ ### Switch语句 / 多态滥用
73
+ - 大量switch/if-else判断类型
74
+ - 违反开闭原则(新增类型需要修改多处)
75
+ - 可以用多态替代的类型判断
76
+
77
+ ### 临时字段 (Temporary Field)
78
+ - 仅在特定条件下使用的字段
79
+ - 对象生命周期中大部分时间该字段为null
80
+ - 字段含义随场景变化
81
+
82
+ ### 消息链 (Message Chains)
83
+ - `a.b.c.d.doSomething()`
84
+ - 过度导航(违反得墨忒耳定律)
85
+ - 紧耦合的实现细节暴露
86
+
87
+ ### 过度使用null (Null Checks)
88
+ - 大量的null检查散落在各处
89
+ - null表示多种不同含义
90
+ - 可以考虑Null Object模式或Optional
91
+
92
+ ### 魔法数字/字符串 (Magic Numbers/Strings)
93
+ - 硬编码的数值(如 86400、1024)
94
+ - 未命名的布尔值(`true`/`false` 参数)
95
+ - 重复出现的字符串常量
96
+
97
+ ### 注释掉的代码
98
+ - 版本控制中遗留的注释代码块
99
+ - 无用的TODO标记
100
+ - 过时的注释与代码不符
101
+
102
+ ### 命名问题
103
+ - 模糊命名(data、temp、obj)
104
+ - 不一致命名风格(camelCase vs snake_case)
105
+ - 误导性命名(名不副实)
106
+ - 缩写不清晰(除非是通用缩写)
107
+
108
+ ## 设计问题类
109
+
110
+ ### SOLID原则违反
111
+
112
+ **单一职责原则 (SRP)**
113
+ - 一个类/方法改变有多个原因
114
+ - 不同客户端依赖类的不同部分
115
+ - 高内聚的破坏信号
116
+
117
+ **开闭原则 (OCP)**
118
+ - 新增功能需要修改现有代码
119
+ - 大量的if/else或switch
120
+ - 抽象不足导致扩展困难
121
+
122
+ **里氏替换原则 (LSP)**
123
+ - 子类违反父类契约
124
+ - 子类抛出父类未声明的异常
125
+ - 子类强化前置条件或弱化后置条件
126
+
127
+ **接口隔离原则 (ISP)**
128
+ - 接口臃肿(客户被迫依赖不需要的方法)
129
+ - 胖接口(God Interface)
130
+
131
+ **依赖倒置原则 (DIP)**
132
+ - 高层模块依赖低层模块的具体实现
133
+ - 抽象依赖具体(而非具体依赖抽象)
134
+
135
+ ### 高耦合/低内聚
136
+ - 修改一个类需要修改很多其他类
137
+ - 类之间依赖关系过于复杂(蜘蛛网)
138
+ - 一个类知道太多其他类的内部细节
139
+
140
+ ### 设计模式误用
141
+
142
+ **继承滥用**
143
+ - "是一个"关系不成立却使用继承
144
+ - 子类仅复用代码而非扩展行为
145
+ - 可以用组合却用了继承
146
+
147
+ **过度工程(过早抽象)**
148
+ - 为不存在的需求设计
149
+ - 过度使用设计模式
150
+ - 简单问题复杂化
151
+
152
+ **贫血模型**
153
+ - 只有getter/setter的类
154
+ - 业务逻辑全部在Service中
155
+ - 缺乏封装(直接暴露内部状态)
156
+
157
+ ### API设计问题
158
+ - 方法命名不清晰(动词使用不当)
159
+ - 参数顺序不符合直觉
160
+ - 返回值设计不合理(如用null表示空集合)
161
+ - 副作用不明显(方法做了命名之外的事)
162
+
163
+ ### 可见性问题
164
+ - 过度使用public(所有字段方法都公开)
165
+ - 应该private的字段暴露出去
166
+ - 包可见性使用不当
167
+
168
+ ## 语言特定坏味道
169
+
170
+ ### Java/Kotlin
171
+ - 原始类型偏执(过度使用int/long而非封装类型)
172
+ - 集合的原始类型使用(`List` vs `List<String>`)
173
+ - 不必要的装箱/拆箱
174
+ - Stream API误用(过度复杂或性能差)
175
+ - Optional作为字段或方法参数(应作为返回类型)
176
+
177
+ ### Python
178
+ - 使用list作为默认参数(可变默认参数陷阱)
179
+ - 捕获所有异常过于宽泛(`except:`)
180
+ - 循环中修改被迭代的列表
181
+ - 不使用上下文管理器(`with`)管理资源
182
+
183
+ ### JavaScript/TypeScript
184
+ - 隐式类型转换(`==` vs `===`)
185
+ - 回调地狱(未使用Promise/async-await)
186
+ - var的滥用(应使用let/const)
187
+ - this绑定问题
188
+ - any类型的滥用(TypeScript)
189
+
190
+ ### Go
191
+ - 错误检查被忽视(`_ = doSomething()`)
192
+ - 不必要的接口(仅有一个实现)
193
+ - 过早抽象(接口由消费者定义)
194
+ - goroutine泄漏(未正确关闭channel或wait)
195
+
196
+ ### C/C++
197
+ - 内存泄漏(new/malloc未对应delete/free)
198
+ - 野指针(使用已释放内存)
199
+ - 缓冲区溢出(数组越界写入)
200
+ - 整数溢出
201
+ - 未定义行为(UB)
@@ -0,0 +1,123 @@
1
+ # 实现意图深度参考
2
+
3
+ > 当 coding skill 路由到"实现"意图时按需加载。
4
+
5
+ ---
6
+
7
+ ## Sub-agent 使用原则
8
+
9
+ ### 何时委托给 sub-agent
10
+
11
+ | 场景 | 委托方式 | 期望回传 |
12
+ |------|---------|---------|
13
+ | 不确定改动影响哪些文件 | Agent(subagent_type: "Explore") | 影响文件列表 + 风险点 |
14
+ | 需要理解调用链 | Agent(subagent_type: "Explore") | 调用者/被调用者 + 数据流 |
15
+ | 搜索项目中的已有模式 | Agent(subagent_type: "Explore") | 相似实现 + 可复用工具方法 |
16
+ | 分析模块架构 | Agent(subagent_type: "Explore") | 关键组件 + 交互关系图 |
17
+
18
+ ### 如何写好 sub-agent prompt
19
+
20
+ **原则**:告诉 sub-agent 你需要什么结论,不要规定搜索步骤。
21
+
22
+ **好**:
23
+ ```
24
+ 分析 OrderService.createOrder() 的完整调用链。
25
+ 我需要知道:
26
+ 1. 哪些类直接调用了这个方法
27
+ 2. 这个方法内部依赖了哪些外部服务
28
+ 3. 修改它的返回值类型会影响哪些下游
29
+ ```
30
+
31
+ **差**:
32
+ ```
33
+ 先 grep OrderService,再读每个文件,然后...
34
+ ```
35
+
36
+ ### 何时不用 sub-agent
37
+
38
+ - 精确知道要读哪个文件 → 直接 Read
39
+ - 搜索一个已知符号 → 直接 Grep
40
+ - 改动位置已确定 → 直接 Edit
41
+
42
+ ---
43
+
44
+ ## Plan Mode 使用要点
45
+
46
+ ### 进入 Plan Mode 的信号
47
+
48
+ - 变更涉及 3+ 文件
49
+ - 需要用户确认方案(多种可行路径)
50
+ - 涉及接口变更或公共 API
51
+ - 不确定变更边界
52
+
53
+ ### Plan 应包含
54
+
55
+ 1. **变更目标**:一句话说清楚要达成什么
56
+ 2. **影响文件清单**:列出每个需要改动的文件及改动原因
57
+ 3. **实施步骤**:带验证点的步骤序列
58
+ 4. **风险与回退**:识别主要风险点,说明回退方案
59
+
60
+ ### Plan 不应包含
61
+
62
+ - 冗余的背景分析(用户已经知道)
63
+ - 过度详细的代码片段(执行时再写)
64
+ - 风险清单和 RACI 表(除非用户要求)
65
+
66
+ ---
67
+
68
+ ## 状态文件使用要点
69
+
70
+ 仅深度任务需要状态文件。参见 SKILL.md 第 4 节"外化"部分的模板。
71
+
72
+ ### 何时创建
73
+
74
+ - 预计修改 10+ 文件
75
+ - 需要分多个阶段完成
76
+ - 可能跨会话
77
+
78
+ ### 何时不创建
79
+
80
+ - 能在一轮 Plan Mode 循环内完成的任务
81
+ - 轻量任务
82
+
83
+ ### Phase 划分原则
84
+
85
+ - 每个 Phase 有独立的验证点(编译/测试可通过)
86
+ - 先核心后周边:Phase 1 先让主路径跑通
87
+ - Phase 之间松耦合:某个 Phase 失败不阻塞其他
88
+
89
+ ---
90
+
91
+ ## 验证策略
92
+
93
+ ### 编译验证
94
+
95
+ 改完就编译,不攒到最后:
96
+ ```bash
97
+ # Java/Maven
98
+ mvn compile -pl <module> -DskipTests
99
+
100
+ # Node
101
+ npm run build
102
+
103
+ # Go
104
+ go build ./...
105
+ ```
106
+
107
+ ### 测试验证
108
+
109
+ 运行变更相关的测试:
110
+ ```bash
111
+ # 指定测试类
112
+ mvn test -Dtest=<TestClass> -pl <module>
113
+
114
+ # 指定测试文件
115
+ npm test -- --grep "<pattern>"
116
+ ```
117
+
118
+ ### 回归检查
119
+
120
+ 高风险变更(公共接口/核心逻辑)运行完整测试套件:
121
+ ```bash
122
+ mvn test -pl <module>
123
+ ```
@@ -0,0 +1,211 @@
1
+ # 单元测试意图深度参考
2
+
3
+ > 当 coding skill 路由到"测试"意图时按需加载。
4
+ > 浓缩自实战经验,每条规则背后都有踩坑记录。
5
+
6
+ ---
7
+
8
+ ## 执行策略
9
+
10
+ **批量生成 + 统一编译 + 错误修复**,不要逐个测试方法编写验证。
11
+
12
+ 1. 分析被测类 → 2. 一次性生成完整测试类 → 3. 编译验证 → 4. 运行修复 → 5. 覆盖率检查
13
+
14
+ ---
15
+
16
+ ## 框架检测与适配
17
+
18
+ 读取 pom.xml / build.gradle 确定框架组合:
19
+
20
+ | 框架组合 | 类注解 | Mock 注入 | 注意事项 |
21
+ |---------|--------|----------|---------|
22
+ | JUnit 5 + Mockito | `@ExtendWith(MockitoExtension.class)` | `@InjectMocks` 自动注入 | 推荐方案 |
23
+ | JUnit 4 + Mockito | `@RunWith(MockitoJUnitRunner.class)` | `@InjectMocks` 自动注入 | |
24
+ | JUnit 4 + PowerMock | `@RunWith(PowerMockRunner.class)` | **必须手动注入 @Autowired 字段** | 见下方陷阱 #1 |
25
+
26
+ ---
27
+
28
+ ## Mock 陷阱(必读)
29
+
30
+ ### 陷阱 1: PowerMock + @Autowired 手动注入
31
+
32
+ PowerMock 的 `@InjectMocks` 不能处理 `@Autowired` 字段,必须反射注入:
33
+
34
+ ```java
35
+ @Before
36
+ public void setUp() throws Exception {
37
+ MockitoAnnotations.initMocks(this);
38
+ injectField("repository", repository);
39
+ injectField("externalService", externalService);
40
+ }
41
+
42
+ private void injectField(String name, Object value) throws Exception {
43
+ Field field = ServiceUnderTest.class.getDeclaredField(name);
44
+ field.setAccessible(true);
45
+ field.set(serviceUnderTest, value);
46
+ }
47
+ ```
48
+
49
+ ### 陷阱 2: thenReturn 中调用 mock 方法
50
+
51
+ ```java
52
+ // WRONG — 触发 UnfinishedStubbingException
53
+ when(service.getData()).thenReturn(buildData(mockObj));
54
+
55
+ // RIGHT — 使用固定值
56
+ when(service.getData()).thenReturn(buildData(1, 2, 3));
57
+ // 或使用 thenAnswer
58
+ when(service.getData()).thenAnswer(inv -> buildData(mockObj.getId()));
59
+ ```
60
+
61
+ ### 陷阱 3: stream/lambda 中的隐藏依赖
62
+
63
+ 被测代码中 stream 操作内的方法调用容易遗漏:
64
+ ```java
65
+ rights.stream().map(rightV2 -> {
66
+ RightKey key = rightV2.rightKey(); // 需要 mock
67
+ Integer times = rightV2.getTimes(cmd); // 需要 mock
68
+ Long count = rightV2.activityAllCount(); // 需要 mock
69
+ });
70
+ ```
71
+ **必须**完整阅读方法体,为每个 mock 对象列出"方法调用清单"。
72
+
73
+ ### 陷阱 4: 实体类实例化方式
74
+
75
+ | 类型 | 实例化方式 | 原因 |
76
+ |------|----------|------|
77
+ | 项目内部 DTO/VO/Entity | `new` + setter | 有完整 setter |
78
+ | 接口、抽象类 | `mock()` | 无法实例化 |
79
+ | 外部 SDK 实体类 | `mock()` + `when().thenReturn()` | 通常无 public setter |
80
+
81
+ ```java
82
+ // WRONG — 外部 SDK 类没有 setter
83
+ AccountRealName account = new AccountRealName();
84
+ account.setEnFirstName("John"); // 编译错误
85
+
86
+ // RIGHT
87
+ AccountRealName account = mock(AccountRealName.class);
88
+ when(account.getEnFirstName()).thenReturn("John");
89
+ ```
90
+
91
+ **不确定时**:先查看已有测试代码或源代码确认。
92
+
93
+ ### 陷阱 5: 父类已有 mock
94
+
95
+ 检查测试父类是否已定义 mock 字段,子类不要重复定义:
96
+ ```java
97
+ // 父类已有
98
+ @Mock protected DTOMapper dtoMapper;
99
+ // 子类中 —— 不要再写 @Mock DTOMapper dtoMapper!
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 测试设计
105
+
106
+ ### 命名规范
107
+
108
+ `test{MethodName}_{Scenario}_{ExpectedResult}`
109
+
110
+ ### Given-When-Then 结构
111
+
112
+ ```java
113
+ @Test
114
+ void testCreateOrder_WithValidRequest_ShouldReturnCreatedOrder() {
115
+ // Given — 准备数据和 mock
116
+ CreateOrderRequest request = buildValidRequest();
117
+ given(inventoryClient.checkStock(any(), anyInt())).willReturn(true);
118
+
119
+ // When — 执行被测方法
120
+ Order result = orderService.createOrder(request);
121
+
122
+ // Then — 验证结果和行为
123
+ assertThat(result.getStatus()).isEqualTo(OrderStatus.CREATED);
124
+ verify(orderRepository).save(any(Order.class));
125
+ }
126
+ ```
127
+
128
+ ### 每个方法的测试用例矩阵
129
+
130
+ | 类型 | 数量 | 目的 |
131
+ |------|------|------|
132
+ | 正常流程 | 1+ | 核心路径验证 |
133
+ | null/空参数 | 每参数 1 | 防御性检查 |
134
+ | 边界值 | 每参数 1-2 | 极值探测 |
135
+ | 异常流程 | 每异常 1 | 错误处理验证 |
136
+ | 负面验证 | 1-2 | 确认不该发生的事没发生 |
137
+
138
+ ### 行为测试优先
139
+
140
+ 测试"做了什么"而非"怎么做的":
141
+ ```java
142
+ // GOOD — 验证业务行为
143
+ verify(inventoryClient).decreaseStock("product_123", 9);
144
+
145
+ // BAD — 验证实现细节
146
+ verify(inventoryDao).update(eq("product_123"), eq(9));
147
+ ```
148
+
149
+ ---
150
+
151
+ ## 覆盖率目标
152
+
153
+ | 指标 | 目标 |
154
+ |------|------|
155
+ | 行覆盖率 | >= 80% |
156
+ | 分支覆盖率 | >= 70% |
157
+ | 核心类行覆盖率 | >= 90% |
158
+
159
+ ```bash
160
+ mvn test jacoco:report -pl <module>
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 常见编译/运行错误速查
166
+
167
+ | 错误 | 根因 | 修复 |
168
+ |------|------|------|
169
+ | NPE: mock 对象为 null | 未调用 initMocks / PowerMock 未手动注入 | 检查 setUp 方法 |
170
+ | NPE: mock 方法返回 null | 未 stub 某个方法调用 | 补充 when().thenReturn(),集合返回 emptyList |
171
+ | UnfinishedStubbingException | thenReturn 中调用了 mock | 改用固定值或 thenAnswer |
172
+ | Wanted but not invoked | verify 的方法没被实际调用 | 检查代码路径,确认方法确实被调用 |
173
+ | 编译错误:找不到 setter | 对外部 SDK 类用了 new + setter | 改用 mock |
174
+ | 类型不匹配 | 参数类型错误 | 检查 setter/构造函数期望的类型 |
175
+
176
+ ---
177
+
178
+ ## 静态方法 Mock
179
+
180
+ **JUnit 5 + Mockito-inline**:
181
+ ```java
182
+ try (MockedStatic<StaticClass> mocked = mockStatic(StaticClass.class)) {
183
+ mocked.when(StaticClass::staticMethod).thenReturn(result);
184
+ // test code
185
+ }
186
+ ```
187
+
188
+ **PowerMockito**:
189
+ ```java
190
+ @RunWith(PowerMockRunner.class)
191
+ @PrepareForTest({StaticClass.class})
192
+ public class MyTest {
193
+ @Before
194
+ public void setUp() {
195
+ PowerMockito.mockStatic(StaticClass.class);
196
+ when(StaticClass.staticMethod()).thenReturn(result);
197
+ }
198
+ }
199
+ ```
200
+
201
+ ---
202
+
203
+ ## 生成前检查清单
204
+
205
+ - [ ] 完整阅读被测类方法体(包括私有方法、stream/lambda)
206
+ - [ ] 检查测试父类已有 mock 定义
207
+ - [ ] 为每个 mock 对象列出方法调用清单
208
+ - [ ] 确认实体类实例化方式(mock vs new+setter)
209
+ - [ ] 确认 setter 参数类型正确
210
+ - [ ] 集合类返回 emptyList 而非 null
211
+ - [ ] 不在 thenReturn 中调用 mock 方法