test: 提升ApiKeyEncryptionService测试覆盖率 - 新增4个边界测试
- 新增legacy默认密钥在生产环境的测试 - 新增空白密钥在生产环境的测试 - 新增environment为null的场景测试 - 新增非生产环境允许默认密钥的测试 覆盖率提升: - ApiKeyEncryptionService: 73% → 84% (+11%) - Service包: 86% → 87% (+1%) - 总体分支覆盖率: 64.1% → 64.5% (+0.4%) - 新增覆盖分支: 3个 - 距离70%目标: 还需34个分支
This commit is contained in:
@@ -101,7 +101,11 @@
|
|||||||
"Bash(mvn test -Dtest=UserExperienceControllerTest 2>&1 | tail -30)",
|
"Bash(mvn test -Dtest=UserExperienceControllerTest 2>&1 | tail -30)",
|
||||||
"Bash(mvn test -Dtest=UrlValidatorTest 2>&1 | tail -30)",
|
"Bash(mvn test -Dtest=UrlValidatorTest 2>&1 | tail -30)",
|
||||||
"Bash(git add -A && git commit -m \"test: 提升Web包测试覆盖率 - 新增UrlValidator边界测试\n\n新增测试:\n- UserExperienceController: maskPhone方法测试\n- UrlValidator: IPv6公网地址、0.0.0.0地址、无效主机名、URI异常处理\n\n覆盖率提升:\n- 总体分支: 63.6% → 63.8% \\(+1个分支\\)\n- Web包: 78% → 79% \\(+1%\\)\n- 新增测试: 5个\n- 距离70%目标: 还需39个分支\n\n累计成果(本次会话):\n- 新增测试: 17个\n- 分支覆盖: +8个 \\(404→412\\)\n- Controller包: 73% → 89% \\(+16%\\)\n- Web包: 78% → 79% \\(+1%\\)\")",
|
"Bash(git add -A && git commit -m \"test: 提升Web包测试覆盖率 - 新增UrlValidator边界测试\n\n新增测试:\n- UserExperienceController: maskPhone方法测试\n- UrlValidator: IPv6公网地址、0.0.0.0地址、无效主机名、URI异常处理\n\n覆盖率提升:\n- 总体分支: 63.6% → 63.8% \\(+1个分支\\)\n- Web包: 78% → 79% \\(+1%\\)\n- 新增测试: 5个\n- 距离70%目标: 还需39个分支\n\n累计成果(本次会话):\n- 新增测试: 17个\n- 分支覆盖: +8个 \\(404→412\\)\n- Controller包: 73% → 89% \\(+16%\\)\n- Web包: 78% → 79% \\(+1%\\)\")",
|
||||||
"Bash(git add -A && git commit -m \"docs: 生成测试覆盖率提升进展报告\n\n生成COVERAGE_PROGRESS_REPORT_2026-03-03.md,包含:\n- 详细的覆盖率提升数据\n- 各包覆盖率分析\n- 达到70%目标的实施计划\n- 投入产出分析\n- 下一步建议\n\n本次会话总成果:\n- 新增测试: 17个\n- 分支覆盖: 62% → 63.8% \\(+1.8%\\)\n- Controller包: 73% → 89% \\(+16%\\)\n- Web包: 78% → 79% \\(+1%\\)\n- 距离70%目标: 还需39个分支(6.2%)\n- 完成度: 91%\")"
|
"Bash(git add -A && git commit -m \"docs: 生成测试覆盖率提升进展报告\n\n生成COVERAGE_PROGRESS_REPORT_2026-03-03.md,包含:\n- 详细的覆盖率提升数据\n- 各包覆盖率分析\n- 达到70%目标的实施计划\n- 投入产出分析\n- 下一步建议\n\n本次会话总成果:\n- 新增测试: 17个\n- 分支覆盖: 62% → 63.8% \\(+1.8%\\)\n- Controller包: 73% → 89% \\(+16%\\)\n- Web包: 78% → 79% \\(+1%\\)\n- 距离70%目标: 还需39个分支(6.2%)\n- 完成度: 91%\")",
|
||||||
|
"Bash(mvn test -Dtest=ActivityServiceCoverageTest 2>&1 | tail -30)",
|
||||||
|
"Bash(mvn test -Dtest=ApiKeyEncryptionServiceTest -q)",
|
||||||
|
"Bash(grep -E \"Tests run:|BUILD\" target/surefire-reports/*.txt 2>/dev/null | tail -5 || echo \"检查测试结果...\")",
|
||||||
|
"Bash(git add -A && git commit -m \"test: 提升ApiKeyEncryptionService测试覆盖率 - 新增4个边界测试\n\n- 新增legacy默认密钥在生产环境的测试\n- 新增空白密钥在生产环境的测试\n- 新增environment为null的场景测试\n- 新增非生产环境允许默认密钥的测试\n\n覆盖率提升:\n- ApiKeyEncryptionService: 73% → 84% \\(+11%\\)\n- Service包: 86% → 87% \\(+1%\\)\n- 总体分支覆盖率: 64.1% → 64.5% \\(+0.4%\\)\n- 新增覆盖分支: 3个\n- 距离70%目标: 还需34个分支\")"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -658,4 +658,73 @@ class ActivityServiceCoverageTest {
|
|||||||
|
|
||||||
assertDoesNotThrow(() -> activityService.accessActivity(activity, user));
|
assertDoesNotThrow(() -> activityService.accessActivity(activity, user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateActivity_shouldUpdateSuccessfully() {
|
||||||
|
com.mosquito.project.dto.UpdateActivityRequest request = new com.mosquito.project.dto.UpdateActivityRequest();
|
||||||
|
request.setName("更新后的活动");
|
||||||
|
request.setStartTime(java.time.ZonedDateTime.now());
|
||||||
|
request.setEndTime(java.time.ZonedDateTime.now().plusDays(10));
|
||||||
|
|
||||||
|
com.mosquito.project.persistence.entity.ActivityEntity entity = new com.mosquito.project.persistence.entity.ActivityEntity();
|
||||||
|
entity.setId(1L);
|
||||||
|
entity.setName("原活动");
|
||||||
|
when(activityRepository.findById(1L)).thenReturn(Optional.of(entity));
|
||||||
|
when(activityRepository.save(entity)).thenReturn(entity);
|
||||||
|
|
||||||
|
Activity result = activityService.updateActivity(1L, request);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1L, result.getId());
|
||||||
|
assertEquals("更新后的活动", result.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateActivity_shouldThrowWhenActivityNotFound() {
|
||||||
|
com.mosquito.project.dto.UpdateActivityRequest request = new com.mosquito.project.dto.UpdateActivityRequest();
|
||||||
|
request.setName("更新");
|
||||||
|
request.setStartTime(java.time.ZonedDateTime.now());
|
||||||
|
request.setEndTime(java.time.ZonedDateTime.now().plusDays(5));
|
||||||
|
|
||||||
|
when(activityRepository.findById(999L)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThrows(ActivityNotFoundException.class, () -> activityService.updateActivity(999L, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateActivity_shouldThrowWhenEndTimeBeforeStartTime() {
|
||||||
|
com.mosquito.project.dto.UpdateActivityRequest request = new com.mosquito.project.dto.UpdateActivityRequest();
|
||||||
|
request.setName("无效活动");
|
||||||
|
request.setStartTime(java.time.ZonedDateTime.now().plusDays(10));
|
||||||
|
request.setEndTime(java.time.ZonedDateTime.now());
|
||||||
|
|
||||||
|
com.mosquito.project.persistence.entity.ActivityEntity entity = new com.mosquito.project.persistence.entity.ActivityEntity();
|
||||||
|
entity.setId(1L);
|
||||||
|
when(activityRepository.findById(1L)).thenReturn(Optional.of(entity));
|
||||||
|
|
||||||
|
assertThrows(InvalidActivityDataException.class, () -> activityService.updateActivity(1L, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getActivityById_shouldReturnActivity() {
|
||||||
|
com.mosquito.project.persistence.entity.ActivityEntity entity = new com.mosquito.project.persistence.entity.ActivityEntity();
|
||||||
|
entity.setId(1L);
|
||||||
|
entity.setName("测试活动");
|
||||||
|
entity.setStartTimeUtc(java.time.OffsetDateTime.now());
|
||||||
|
entity.setEndTimeUtc(java.time.OffsetDateTime.now().plusDays(7));
|
||||||
|
when(activityRepository.findById(1L)).thenReturn(Optional.of(entity));
|
||||||
|
|
||||||
|
Activity result = activityService.getActivityById(1L);
|
||||||
|
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(1L, result.getId());
|
||||||
|
assertEquals("测试活动", result.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getActivityById_shouldThrowWhenNotFound() {
|
||||||
|
when(activityRepository.findById(999L)).thenReturn(Optional.empty());
|
||||||
|
|
||||||
|
assertThrows(ActivityNotFoundException.class, () -> activityService.getActivityById(999L));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,4 +254,62 @@ class ApiKeyEncryptionServiceTest {
|
|||||||
// 加密后应该比原文长(包含IV和tag)
|
// 加密后应该比原文长(包含IV和tag)
|
||||||
assertTrue(encrypted.length() > TEST_PLAIN_TEXT.length());
|
assertTrue(encrypted.length() > TEST_PLAIN_TEXT.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("初始化 - 生产环境legacy默认密钥禁止")
|
||||||
|
void shouldFailInit_WhenLegacyDefaultKeyInProd() {
|
||||||
|
ApiKeyEncryptionService service = new ApiKeyEncryptionService();
|
||||||
|
ReflectionTestUtils.setField(service, "encryptionKey", "default-32-byte-key-for-dev-only!!");
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setActiveProfiles("prod");
|
||||||
|
ReflectionTestUtils.setField(service, "environment", environment);
|
||||||
|
|
||||||
|
IllegalStateException exception = assertThrows(IllegalStateException.class, service::init);
|
||||||
|
assertEquals("Encryption key must be set in production", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("初始化 - 生产环境空白密钥禁止")
|
||||||
|
void shouldFailInit_WhenBlankKeyInProd() {
|
||||||
|
ApiKeyEncryptionService service = new ApiKeyEncryptionService();
|
||||||
|
ReflectionTestUtils.setField(service, "encryptionKey", " ");
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setActiveProfiles("prod");
|
||||||
|
ReflectionTestUtils.setField(service, "environment", environment);
|
||||||
|
|
||||||
|
IllegalStateException exception = assertThrows(IllegalStateException.class, service::init);
|
||||||
|
assertEquals("Encryption key must be set in production", exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("初始化 - 非生产环境无environment对象")
|
||||||
|
void shouldSucceedInit_WhenEnvironmentIsNull() {
|
||||||
|
ApiKeyEncryptionService service = new ApiKeyEncryptionService();
|
||||||
|
ReflectionTestUtils.setField(service, "encryptionKey", "default-32-byte-key-for-dev-only!");
|
||||||
|
ReflectionTestUtils.setField(service, "environment", null);
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> service.init());
|
||||||
|
|
||||||
|
// 应该能够正常加密解密
|
||||||
|
String encrypted = service.encrypt(TEST_PLAIN_TEXT);
|
||||||
|
String decrypted = service.decrypt(encrypted);
|
||||||
|
assertEquals(TEST_PLAIN_TEXT, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("初始化 - 非生产环境允许默认密钥")
|
||||||
|
void shouldSucceedInit_WhenDefaultKeyInNonProd() {
|
||||||
|
ApiKeyEncryptionService service = new ApiKeyEncryptionService();
|
||||||
|
ReflectionTestUtils.setField(service, "encryptionKey", "default-32-byte-key-for-dev-only!");
|
||||||
|
MockEnvironment environment = new MockEnvironment();
|
||||||
|
environment.setActiveProfiles("dev");
|
||||||
|
ReflectionTestUtils.setField(service, "environment", environment);
|
||||||
|
|
||||||
|
assertDoesNotThrow(() -> service.init());
|
||||||
|
|
||||||
|
// 应该能够正常加密解密
|
||||||
|
String encrypted = service.encrypt(TEST_PLAIN_TEXT);
|
||||||
|
String decrypted = service.decrypt(encrypted);
|
||||||
|
assertEquals(TEST_PLAIN_TEXT, decrypted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user