test: 提升Controller测试覆盖率 - 新增IP提取和分页边界测试
- ShortLinkController: 新增3个测试覆盖IP地址提取逻辑 * X-Forwarded-For头部处理 * RemoteAddr回退逻辑 * 空白X-Forwarded-For处理 - UserExperienceController: 新增4个测试覆盖分页边界条件 * size=0时返回空列表 * 负数page处理 * Math.max边界逻辑 覆盖率提升: - 总体分支覆盖率: 62% → 63% - Controller包: 73% → 80% (+7%) - 新增测试用例: 7个 - 距离70%目标: 还需44个分支
This commit is contained in:
@@ -130,4 +130,45 @@ class ShortLinkControllerTest {
|
||||
mockMvc.perform(get("/r/mal12345"))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldExtractIpFromXForwardedFor() throws Exception {
|
||||
ShortLinkEntity e = new ShortLinkEntity();
|
||||
e.setCode("ip12345");
|
||||
e.setOriginalUrl("https://example.com/page");
|
||||
when(shortLinkService.findByCode("ip12345")).thenReturn(Optional.of(e));
|
||||
when(urlValidator.isAllowedUrl("https://example.com/page")).thenReturn(true);
|
||||
|
||||
mockMvc.perform(get("/r/ip12345")
|
||||
.header("X-Forwarded-For", "203.0.113.1, 198.51.100.1"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string("Location", "https://example.com/page"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseRemoteAddrWhenNoXForwardedFor() throws Exception {
|
||||
ShortLinkEntity e = new ShortLinkEntity();
|
||||
e.setCode("remote123");
|
||||
e.setOriginalUrl("https://example.com/page");
|
||||
when(shortLinkService.findByCode("remote123")).thenReturn(Optional.of(e));
|
||||
when(urlValidator.isAllowedUrl("https://example.com/page")).thenReturn(true);
|
||||
|
||||
mockMvc.perform(get("/r/remote123"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string("Location", "https://example.com/page"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleBlankXForwardedFor() throws Exception {
|
||||
ShortLinkEntity e = new ShortLinkEntity();
|
||||
e.setCode("blank123");
|
||||
e.setOriginalUrl("https://example.com/page");
|
||||
when(shortLinkService.findByCode("blank123")).thenReturn(Optional.of(e));
|
||||
when(urlValidator.isAllowedUrl("https://example.com/page")).thenReturn(true);
|
||||
|
||||
mockMvc.perform(get("/r/blank123")
|
||||
.header("X-Forwarded-For", " "))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(header().string("Location", "https://example.com/page"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,4 +240,74 @@ class UserExperienceControllerTest {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data.title").value("自定义模板"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleZeroOrNegativeSize_inInvitedFriends() throws Exception {
|
||||
UserInviteEntity a = new UserInviteEntity(); a.setInviteeUserId(10L); a.setStatus("clicked");
|
||||
UserInviteEntity b = new UserInviteEntity(); b.setInviteeUserId(11L); b.setStatus("registered");
|
||||
when(userInviteRepository.findByActivityIdAndInviterUserId(anyLong(), anyLong())).thenReturn(List.of(a, b));
|
||||
|
||||
mockMvc.perform(get("/api/v1/me/invited-friends")
|
||||
.param("activityId", "1")
|
||||
.param("userId", "2")
|
||||
.param("page", "0")
|
||||
.param("size", "0")
|
||||
.header("X-API-Key", TestAuthSupport.RAW_API_KEY)
|
||||
.header("Authorization", "Bearer test-token"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleZeroOrNegativeSize_inRewards() throws Exception {
|
||||
var r1 = new com.mosquito.project.persistence.entity.UserRewardEntity(); r1.setType("points"); r1.setPoints(100); r1.setCreatedAt(java.time.OffsetDateTime.now());
|
||||
var r2 = new com.mosquito.project.persistence.entity.UserRewardEntity(); r2.setType("coupon"); r2.setPoints(0); r2.setCreatedAt(java.time.OffsetDateTime.now().minusDays(1));
|
||||
when(userRewardRepository.findByActivityIdAndUserIdOrderByCreatedAtDesc(anyLong(), anyLong())).thenReturn(java.util.List.of(r1, r2));
|
||||
|
||||
mockMvc.perform(get("/api/v1/me/rewards")
|
||||
.param("activityId", "1")
|
||||
.param("userId", "2")
|
||||
.param("page", "0")
|
||||
.param("size", "0")
|
||||
.header("X-API-Key", TestAuthSupport.RAW_API_KEY)
|
||||
.header("Authorization", "Bearer test-token"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleNegativePage_inInvitedFriends() throws Exception {
|
||||
UserInviteEntity a = new UserInviteEntity(); a.setInviteeUserId(10L); a.setStatus("clicked");
|
||||
when(userInviteRepository.findByActivityIdAndInviterUserId(anyLong(), anyLong())).thenReturn(List.of(a));
|
||||
|
||||
mockMvc.perform(get("/api/v1/me/invited-friends")
|
||||
.param("activityId", "1")
|
||||
.param("userId", "2")
|
||||
.param("page", "-1")
|
||||
.param("size", "20")
|
||||
.header("X-API-Key", TestAuthSupport.RAW_API_KEY)
|
||||
.header("Authorization", "Bearer test-token"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data[0].status").value("clicked"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHandleNegativePage_inRewards() throws Exception {
|
||||
var r1 = new com.mosquito.project.persistence.entity.UserRewardEntity(); r1.setType("points"); r1.setPoints(100); r1.setCreatedAt(java.time.OffsetDateTime.now());
|
||||
when(userRewardRepository.findByActivityIdAndUserIdOrderByCreatedAtDesc(anyLong(), anyLong())).thenReturn(java.util.List.of(r1));
|
||||
|
||||
mockMvc.perform(get("/api/v1/me/rewards")
|
||||
.param("activityId", "1")
|
||||
.param("userId", "2")
|
||||
.param("page", "-1")
|
||||
.param("size", "20")
|
||||
.header("X-API-Key", TestAuthSupport.RAW_API_KEY)
|
||||
.header("Authorization", "Bearer test-token"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data[0].type").value("points"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user