package com.xuekairui.gateway; import org.junit.jupiter.api.*; import org.springframework.http.MediaType; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * 操作审计日志接口测试 * 覆盖:分页查询、敏感日志查询、用户日志查询、目标操作历史、模块统计、权限校验 */ @DisplayName("操作审计日志接口测试") @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class OperationAuditLogTest extends GatewayBaseTest { private String adminToken() { return generateAccessToken(1L, "13800138000"); } // ==================== 分页查询 ==================== @Test @Order(1) @DisplayName("GET /api/admin/audit-log - 默认分页查询(无筛选条件)") void queryLogs_default_shouldReturnPage() throws Exception { mockMvc.perform(get("/api/admin/audit-log") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()) .andExpect(jsonPath("$.data.total").isNumber()) .andExpect(jsonPath("$.data.current").isNumber()) .andExpect(jsonPath("$.data.size").isNumber()); } @Test @Order(2) @DisplayName("GET /api/admin/audit-log?page=1&size=10 - 自定义分页") void queryLogs_customPagination_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log?page=1&size=10") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.size").value(10)); } @Test @Order(3) @DisplayName("GET /api/admin/audit-log?module=USER - 按模块筛选") void queryLogs_filterByModule_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log?module=USER") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(4) @DisplayName("GET /api/admin/audit-log?operationType=USER_LOGIN - 按操作类型筛选") void queryLogs_filterByOperationType_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log?operationType=USER_LOGIN") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(5) @DisplayName("GET /api/admin/audit-log?operatorId=1 - 按操作人筛选") void queryLogs_filterByOperatorId_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log?operatorId=1") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(6) @DisplayName("GET /api/admin/audit-log?isSensitive=true - 筛选敏感操作") void queryLogs_filterSensitive_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log?isSensitive=true") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(7) @DisplayName("GET /api/admin/audit-log?isSensitive=false - 筛选非敏感操作") void queryLogs_filterNonSensitive_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log?isSensitive=false") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(8) @DisplayName("GET /api/admin/audit-log?startTime=...&endTime=... - 按时间范围筛选") void queryLogs_filterByTimeRange_shouldFilter() throws Exception { mockMvc.perform(get("/api/admin/audit-log") .param("startTime", "2024-01-01T00:00:00") .param("endTime", "2030-12-31T23:59:59") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(9) @DisplayName("GET /api/admin/audit-log - 多条件组合筛选") void queryLogs_multiFilter_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log") .param("module", "USER") .param("operatorId", "1") .param("page", "1") .param("size", "5") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.records").isArray()); } @Test @Order(10) @DisplayName("GET /api/admin/audit-log - 无Token应返回401") void queryLogs_withoutToken_shouldReturn401() throws Exception { mockMvc.perform(get("/api/admin/audit-log")) .andExpect(status().isUnauthorized()); } // ==================== 敏感日志查询 ==================== @Test @Order(20) @DisplayName("GET /api/admin/audit-log/sensitive - 查询敏感操作日志") void getSensitiveLogs_shouldReturnList() throws Exception { mockMvc.perform(get("/api/admin/audit-log/sensitive") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(21) @DisplayName("GET /api/admin/audit-log/sensitive?startTime=... - 带时间筛选") void getSensitiveLogs_withTime_shouldReturnList() throws Exception { mockMvc.perform(get("/api/admin/audit-log/sensitive") .param("startTime", "2024-01-01T00:00:00") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(22) @DisplayName("GET /api/admin/audit-log/sensitive - 无Token应返回401") void getSensitiveLogs_withoutToken_shouldReturn401() throws Exception { mockMvc.perform(get("/api/admin/audit-log/sensitive")) .andExpect(status().isUnauthorized()); } // ==================== 用户操作日志查询 ==================== @Test @Order(30) @DisplayName("GET /api/admin/audit-log/user/{userId} - 查询用户操作日志") void getUserLogs_shouldReturnList() throws Exception { mockMvc.perform(get("/api/admin/audit-log/user/1") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(31) @DisplayName("GET /api/admin/audit-log/user/{userId}?limit=10 - 自定义返回数量") void getUserLogs_customLimit_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log/user/1?limit=10") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(32) @DisplayName("GET /api/admin/audit-log/user/{userId} - 查询不存在的用户应返回空列表") void getUserLogs_nonExistentUser_shouldReturnEmpty() throws Exception { mockMvc.perform(get("/api/admin/audit-log/user/99999") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(33) @DisplayName("GET /api/admin/audit-log/user/{userId} - 无Token应返回401") void getUserLogs_withoutToken_shouldReturn401() throws Exception { mockMvc.perform(get("/api/admin/audit-log/user/1")) .andExpect(status().isUnauthorized()); } // ==================== 目标操作历史查询 ==================== @Test @Order(40) @DisplayName("GET /api/admin/audit-log/target/{targetType}/{targetId} - 查询目标操作历史") void getTargetHistory_shouldReturnList() throws Exception { mockMvc.perform(get("/api/admin/audit-log/target/USER/1") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(41) @DisplayName("GET /api/admin/audit-log/target/{targetType}/{targetId}?limit=20 - 自定义返回数量") void getTargetHistory_customLimit_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log/target/LEVEL_CONFIG/1?limit=20") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()); } @Test @Order(42) @DisplayName("GET /api/admin/audit-log/target/{targetType}/{targetId} - 查询多种目标类型") void getTargetHistory_differentTypes_shouldWork() throws Exception { String[] types = {"USER", "LEVEL_CONFIG", "PLATFORM", "LICENSE", "INVITE", "COUPON"}; for (String type : types) { mockMvc.perform(get("/api/admin/audit-log/target/" + type + "/1") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)); } } @Test @Order(43) @DisplayName("GET /api/admin/audit-log/target/{targetType}/{targetId} - 无Token应返回401") void getTargetHistory_withoutToken_shouldReturn401() throws Exception { mockMvc.perform(get("/api/admin/audit-log/target/USER/1")) .andExpect(status().isUnauthorized()); } // ==================== 模块操作统计 ==================== @Test @Order(50) @DisplayName("GET /api/admin/audit-log/stats?module=USER - 统计模块操作次数") void getStats_shouldReturnCount() throws Exception { mockMvc.perform(get("/api/admin/audit-log/stats?module=USER") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.count").isNumber()); } @Test @Order(51) @DisplayName("GET /api/admin/audit-log/stats?module=LEVEL - 统计等级配置操作") void getStats_levelModule_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log/stats?module=LEVEL") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.count").isNumber()); } @Test @Order(52) @DisplayName("GET /api/admin/audit-log/stats?module=...&startTime=...&endTime=... - 带时间范围统计") void getStats_withTimeRange_shouldWork() throws Exception { mockMvc.perform(get("/api/admin/audit-log/stats") .param("module", "USER") .param("startTime", "2024-01-01T00:00:00") .param("endTime", "2030-12-31T23:59:59") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data.count").isNumber()); } @Test @Order(53) @DisplayName("GET /api/admin/audit-log/stats - 缺少module参数应返回400(参数必填)") void getStats_missingModule_shouldReturnError() throws Exception { mockMvc.perform(get("/api/admin/audit-log/stats") .header("Authorization", "Bearer " + adminToken())) .andExpect(status().is5xxServerError()); } @Test @Order(54) @DisplayName("GET /api/admin/audit-log/stats - 无Token应返回401") void getStats_withoutToken_shouldReturn401() throws Exception { mockMvc.perform(get("/api/admin/audit-log/stats?module=USER")) .andExpect(status().isUnauthorized()); } }