11 KiB
测试改进会话总结 - 2026-02-06 (最终确认版)
本次会话成果
本次会话成功创建并验证了 17 个新的 Repository 层测试,覆盖 3 个业务模块。
已验证通过的测试
1. Incentive 模块 (4 个测试) ✅ 已验证
文件: IncentiveRecordRepositoryTest.java
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@ContextConfiguration(classes = JunboApplication.class)
- ✅
shouldFindByDateBetween- 根据日期范围查询激励记录 - ✅
shouldFindByEmployeeIdAndDateBetween- 根据员工ID和日期范围查询 - ✅
shouldFindByType- 根据类型查询激励记录 - ✅
shouldCalculateTotalAmountByEmployeeAndDateRange- 计算总金额
验证命令:
./gradlew test --tests "info.panli.junbo.incentive.repository.IncentiveRecordRepositoryTest"
# BUILD SUCCESSFUL in 30s ✅
2. KPA 模块 (5 个测试) ✅ 已验证
文件 1: KpaRecordRepositoryTest.java (3 个测试)
- ✅
shouldFindByYearAndMonth- 根据年月查询 KPA 记录 - ✅
shouldFindByYear- 根据年份查询 KPA 记录 - ✅
shouldFindByYearAndMonthAndTitle- 根据年月标题查询
文件 2: KpaEmployeeScoreRepositoryTest.java (2 个测试)
- ✅
shouldFindByKpaRecordId- 根据 KPA 记录ID查询员工得分 - ✅
shouldFindByEmployeeId- 根据员工ID查询得分记录
验证命令:
./gradlew test --tests "info.panli.junbo.kpa.repository.KpaRecordRepositoryTest" \
--tests "info.panli.junbo.kpa.repository.KpaEmployeeScoreRepositoryTest"
# BUILD SUCCESSFUL in 18s ✅
3. Scrum 模块 (8 个测试) ✅ 已验证
文件 1: SprintRepositoryTest.java (3 个测试)
- ✅
shouldFindByName- 根据名称查询Sprint - ✅
shouldFindByStartDateBetween- 根据开始日期范围查询 - ✅
shouldFindByEndDateAfterAndStartDateBefore- 查询包含指定日期的Sprint
文件 2: StoryRepositoryTest.java (2 个测试)
- ✅
shouldFindBySprintId- 根据Sprint ID查询Story - ✅
shouldFindByTitleContaining- 根据标题关键字查询
文件 3: StoryMemberRepositoryTest.java (3 个测试)
- ✅
shouldFindByStoryId- 根据Story ID查询成员 - ✅
shouldFindByEmployeeId- 根据员工ID查询参与的Story - ✅
shouldFindByStoryIdAndRole- 根据Story ID和角色查询
验证命令:
./gradlew test --tests "*SprintRepositoryTest" \
--tests "*StoryRepositoryTest" \
--tests "*StoryMemberRepositoryTest"
# BUILD SUCCESSFUL in 13s ✅
新增代码
测试文件 (6 个)
src/test/java/info/panli/junbo/incentive/repository/IncentiveRecordRepositoryTest.java- 91 行src/test/java/info/panli/junbo/kpa/repository/KpaRecordRepositoryTest.java- 81 行src/test/java/info/panli/junbo/kpa/repository/KpaEmployeeScoreRepositoryTest.java- 108 行src/test/java/info/panli/junbo/scrum/repository/SprintRepositoryTest.java- 95 行src/test/java/info/panli/junbo/scrum/repository/StoryRepositoryTest.java- 69 行src/test/java/info/panli/junbo/scrum/repository/StoryMemberRepositoryTest.java- 145 行
总计: ~589 行测试代码
生产代码修改 (1 处)
文件: src/main/java/info/panli/junbo/incentive/repository/IncentiveRecordRepository.java
@Query("SELECT COALESCE(SUM(i.amount), 0) FROM IncentiveRecordEntity i " +
"WHERE i.employee.id = :employeeId " +
"AND i.date BETWEEN :startDate AND :endDate")
BigDecimal sumAmountByEmployeeIdAndDateBetween(
@Param("employeeId") Long employeeId,
@Param("startDate") LocalDate startDate,
@Param("endDate") LocalDate endDate);
解决的技术问题
问题 1: BigDecimal 相等性判断
现象: new BigDecimal("2500.00") != new BigDecimal("2500")
根因: isEqualTo() 比较包括 scale,导致数值相同但 scale 不同时判断不相等
解决:
// ❌ 错误
assertThat(total).isEqualTo(new BigDecimal("2500.00"));
// ✅ 正确
assertThat(total).isEqualByComparingTo(new BigDecimal("2500.00"));
问题 2: 深层包结构的 @DataJpaTest 配置
现象: Unable to find a @SpringBootConfiguration
根因: @DataJpaTest 在深层包(如 info.panli.junbo.kpa.repository)无法自动查找 @SpringBootApplication
解决:
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@ContextConfiguration(classes = JunboApplication.class) // 必须显式指定
class XxxRepositoryTest { }
问题 3: Entity 字段不存在
现象: cannot find symbol: method setCreatedTime(LocalDateTime)
根因: KpaRecordEntity 没有 createdTime 字段
解决: 检查实体定义,移除不存在的字段调用
问题 4: 枚举类型错误
现象: cannot find symbol: variable TESTER
根因: StoryRole 枚举值是 TEST 而不是 TESTER
解决: 使用正确的枚举值 StoryRole.TEST
问题 5: Repository 方法缺失
现象: cannot find symbol: method sumAmountByEmployeeIdAndDateBetween
根因: Repository 接口未定义该方法
解决: 添加自定义查询方法,使用 @Query 注解
Repository 测试标准模板
基于本次经验,建立了 Repository 测试的标准模板:
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@ContextConfiguration(classes = JunboApplication.class)
@DisplayName("Xxx Repository 测试")
class XxxRepositoryTest {
@Autowired
private XxxRepository xxxRepository;
@Autowired
private EmployeeRepository employeeRepository; // 依赖的Repository
@Test
@DisplayName("测试描述")
void testMethod() {
// Given: 准备数据,使用时间戳避免唯一约束
String uniqueName = "Test_" + System.currentTimeMillis();
Entity entity = new Entity();
entity.setName(uniqueName);
Entity saved = xxxRepository.save(entity);
// When: 执行查询
List<Entity> results = xxxRepository.findByXxx(uniqueName);
// Then: 断言
assertThat(results).isNotEmpty();
assertThat(results).anyMatch(e -> e.getName().equals(uniqueName));
}
}
关键要点
- @ContextConfiguration: 深层包必须显式指定
- 时间戳: 使用
System.currentTimeMillis()避免唯一约束冲突 - 级联保存: 先保存依赖实体(如 Employee),再保存主实体
- 事务回滚:
@DataJpaTest自动回滚,无需手动清理 - BigDecimal: 使用
isEqualByComparingTo而非isEqualTo
测试覆盖情况
已测试的 Repository
| 模块 | Repository | 测试方法数 | 状态 |
|---|---|---|---|
| incentive | IncentiveRecordRepository | 4 | ✅ 完成 |
| kpa | KpaRecordRepository | 3 | ✅ 完成 |
| kpa | KpaEmployeeScoreRepository | 2 | ✅ 完成 |
| scrum | SprintRepository | 3 | ✅ 完成 |
| scrum | StoryRepository | 2 | ✅ 完成 |
| scrum | StoryMemberRepository | 3 | ✅ 完成 |
| organization | EmployeeRepository | ~6 | ✅ 已有 |
总计: 7 个 Repository,~23 个测试方法
待测试的 Repository(优先级排序)
| 优先级 | 模块 | Repository | 建议测试数 |
|---|---|---|---|
| 高 | attendance | SignRecordRepository | 4 |
| 高 | attendance | LeaveRecordRepository | 4 |
| 中 | attendance | WorkCalendarRepository | 2 |
| 中 | organization | DepartmentRepository | 3 |
| 低 | organization | DepartmentRelationRepository | 2 |
| 低 | organization | EmployeeAliasRepository | 2 |
文档产出
docs/test-progress-continuation-2026-02-06.md- 中期进度报告docs/test-improvement-final-2026-02-06.md- 详细技术总结docs/repository-test-summary-confirmed-2026-02-06.md- 本文档(确认版)
Git 提交建议
Commit 1: 添加 Repository 方法
git add src/main/java/info/panli/junbo/incentive/repository/IncentiveRecordRepository.java
git commit -m "feat(incentive): 添加金额汇总查询方法
- 为 IncentiveRecordRepository 添加 sumAmountByEmployeeIdAndDateBetween 方法
- 使用 @Query 注解实现 JPQL 查询
- 使用 COALESCE 处理 NULL 值返回 0"
Commit 2: 添加 Repository 测试
git add src/test/java/info/panli/junbo/incentive/repository/
git add src/test/java/info/panli/junbo/kpa/repository/
git add src/test/java/info/panli/junbo/scrum/repository/
git commit -m "test(repository): 添加 Incentive, KPA, Scrum Repository 测试
新增测试:
- IncentiveRecordRepositoryTest: 4个测试 (日期查询、类型查询、金额汇总)
- KpaRecordRepositoryTest: 3个测试 (年月查询)
- KpaEmployeeScoreRepositoryTest: 2个测试 (KPA记录和员工查询)
- SprintRepositoryTest: 3个测试 (名称、日期范围查询)
- StoryRepositoryTest: 2个测试 (Sprint查询、标题搜索)
- StoryMemberRepositoryTest: 3个测试 (Story成员、员工、角色查询)
技术改进:
- 使用 @ContextConfiguration 解决深层包配置查找问题
- 使用 isEqualByComparingTo 解决 BigDecimal 比较问题
- 使用时间戳避免唯一约束冲突
- 建立 Repository 测试标准模板
测试通过率: 100%"
Commit 3: 更新文档
git add docs/
git commit -m "docs(test): 更新测试改进文档
- 添加 test-progress-continuation-2026-02-06.md
- 添加 test-improvement-final-2026-02-06.md
- 添加 repository-test-summary-confirmed-2026-02-06.md
- 记录技术问题解决方案和最佳实践"
下一步计划
短期目标(本周)
-
✅ 完成 Attendance Repository 测试 (+10 测试)
- SignRecordRepository (4个)
- LeaveRecordRepository (4个)
- WorkCalendarRepository (2个)
-
⏳ 补充 API 层测试 (+20 测试)
- IncentiveController (8个)
- KpaController (10个)
- SprintController (2个,基础的)
中期目标(本月)
-
⏳ Service 层测试 (+15 测试)
- KpaService (5个)
- IncentiveService (5个)
- SprintStoryService (5个)
-
⏳ 覆盖率提升
- 目标: 60%+ instruction coverage
- 策略: 重点覆盖 API 和 Service 层
长期目标
- ⏳ 重构 Excel 依赖测试
- 将 19 个 Excel 依赖测试改为 YAML 数据
- 提高测试稳定性和可维护性
总结
本次会话成功完成:
✅ 17 个新测试 - 100% 通过 ✅ 6 个测试文件 - 约 589 行代码 ✅ 1 个新方法 - 金额汇总查询 ✅ 5 个技术问题 - 全部解决 ✅ 1 套标准模板 - Repository 测试模式 ✅ 3 份技术文档 - 完整记录过程
所有测试均已通过验证,可安全提交到代码库。
日期: 2026-02-06 状态: ✅ 已完成并验证 测试通过率: 100% 代码质量: 符合规范