18 changed files with 26 additions and 965 deletions
@ -1,301 +0,0 @@ |
|||||
//package com.zdxt.rest.test;
|
|
||||
//
|
|
||||
//import cn.dev33.satoken.context.mock.SaTokenContextMockUtil;
|
|
||||
//import org.dromara.ZdxtAdminApplication;
|
|
||||
//import org.junit.jupiter.api.*;
|
|
||||
//import org.springframework.beans.factory.annotation.Autowired;
|
|
||||
//import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
|
||||
//import org.springframework.boot.test.context.SpringBootTest;
|
|
||||
//import org.springframework.http.MediaType;
|
|
||||
//import org.springframework.test.web.servlet.MockMvc;
|
|
||||
//import org.springframework.test.web.servlet.MvcResult;
|
|
||||
//
|
|
||||
//import java.nio.charset.StandardCharsets;
|
|
||||
//
|
|
||||
//import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
|
||||
//import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
|
|
||||
//import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
|
||||
//
|
|
||||
///**
|
|
||||
// * AppEnterpriseLoginController 企业端-用户登录接口测试
|
|
||||
// * <p>
|
|
||||
// * 覆盖以下接口:
|
|
||||
// * 1. POST /app-ent/login/siqLogin - 深i企用户登录
|
|
||||
// * </p>
|
|
||||
// * <p>
|
|
||||
// * 注意:此测试需要配置真实的深i企接口地址,或在测试环境中 Mock 相关服务
|
|
||||
// * </p>
|
|
||||
// *
|
|
||||
// * @author zdxt
|
|
||||
// */
|
|
||||
//@SpringBootTest(classes = ZdxtAdminApplication.class)
|
|
||||
//@AutoConfigureMockMvc
|
|
||||
//@DisplayName("AppEnterpriseLoginController 企业端-用户登录接口测试")
|
|
||||
//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
||||
//public class AppEnterpriseLoginControllerTest {
|
|
||||
//
|
|
||||
// @Autowired
|
|
||||
// private MockMvc mockMvc;
|
|
||||
//
|
|
||||
// private static final String BASE_URL = "/app-ent/login";
|
|
||||
// private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e";
|
|
||||
//
|
|
||||
// @BeforeEach
|
|
||||
// public void setUp() {
|
|
||||
// SaTokenContextMockUtil.setMockContext();
|
|
||||
// }
|
|
||||
//
|
|
||||
// @AfterEach
|
|
||||
// public void tearDown() {
|
|
||||
// SaTokenContextMockUtil.clearContext();
|
|
||||
// }
|
|
||||
//
|
|
||||
// // ==================== siqLogin 接口测试 ====================
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 正常请求(需要有效的授权码)")
|
|
||||
// @Test
|
|
||||
// @Order(1)
|
|
||||
// public void testSiqLoginSuccess() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"test_authorization_code\"}";
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
// System.out.println("深i企登录接口响应: " + responseBody);
|
|
||||
//
|
|
||||
// if (responseBody.contains("\"code\":200")) {
|
|
||||
// Assertions.assertTrue(responseBody.contains("token"), "返回数据应包含 token");
|
|
||||
// Assertions.assertTrue(responseBody.contains("userId"), "返回数据应包含 userId");
|
|
||||
// Assertions.assertTrue(responseBody.contains("userName"), "返回数据应包含 userName");
|
|
||||
// Assertions.assertTrue(responseBody.contains("enterpriseId"), "返回数据应包含 enterpriseId");
|
|
||||
// Assertions.assertTrue(responseBody.contains("enterpriseName"), "返回数据应包含 enterpriseName");
|
|
||||
// System.out.println("深i企登录成功,返回了完整的用户和企业信息");
|
|
||||
// } else {
|
|
||||
// System.out.println("深i企登录失败(可能由于授权码无效或深i企接口未配置): " + responseBody);
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 缺少授权码参数应返回失败")
|
|
||||
// @Test
|
|
||||
// @Order(2)
|
|
||||
// public void testSiqLoginMissingCode() throws Exception {
|
|
||||
// String requestBody = "{}";
|
|
||||
//
|
|
||||
// mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andExpect(jsonPath("$.code").value(500));
|
|
||||
//
|
|
||||
// System.out.println("缺少授权码参数返回失败测试成功");
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 空授权码应返回失败")
|
|
||||
// @Test
|
|
||||
// @Order(3)
|
|
||||
// public void testSiqLoginEmptyCode() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"\"}";
|
|
||||
//
|
|
||||
// mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andExpect(jsonPath("$.code").value(500));
|
|
||||
//
|
|
||||
// System.out.println("空授权码返回失败测试成功");
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 无效授权码应返回失败")
|
|
||||
// @Test
|
|
||||
// @Order(4)
|
|
||||
// public void testSiqLoginInvalidCode() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"invalid_code_12345\"}";
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
//
|
|
||||
// if (responseBody.contains("\"code\":500")) {
|
|
||||
// System.out.println("无效授权码返回失败测试成功");
|
|
||||
// } else {
|
|
||||
// System.out.println("注意:无效授权码未返回预期错误,响应: " + responseBody);
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 验证返回数据结构完整性")
|
|
||||
// @Test
|
|
||||
// @Order(5)
|
|
||||
// public void testSiqLoginResponseStructure() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"test_code\"}";
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
// System.out.println("验证返回数据结构响应: " + responseBody);
|
|
||||
//
|
|
||||
// if (responseBody.contains("\"code\":200")) {
|
|
||||
// Assertions.assertTrue(responseBody.contains("\"data\""), "返回数据应包含 data 字段");
|
|
||||
//
|
|
||||
// String data = extractDataJson(responseBody);
|
|
||||
// if (data != null) {
|
|
||||
// Assertions.assertTrue(data.contains("token"), "data 中应包含 token");
|
|
||||
// Assertions.assertTrue(data.contains("userId"), "data 中应包含 userId");
|
|
||||
// Assertions.assertTrue(data.contains("userName"), "data 中应包含 userName");
|
|
||||
// Assertions.assertTrue(data.contains("loginName"), "data 中应包含 loginName");
|
|
||||
// Assertions.assertTrue(data.contains("phonenumber"), "data 中应包含 phonenumber");
|
|
||||
// Assertions.assertTrue(data.contains("enterpriseId"), "data 中应包含 enterpriseId");
|
|
||||
// Assertions.assertTrue(data.contains("enterpriseName"), "data 中应包含 enterpriseName");
|
|
||||
// Assertions.assertTrue(data.contains("enterpriseNumber"), "data 中应包含 enterpriseNumber");
|
|
||||
// System.out.println("返回数据结构完整,包含所有必需字段");
|
|
||||
// }
|
|
||||
// } else {
|
|
||||
// System.out.println("登录失败,无法验证数据结构");
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 重复登录应能正常处理(同一授权码多次调用)")
|
|
||||
// @Test
|
|
||||
// @Order(6)
|
|
||||
// public void testSiqLoginDuplicateCall() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"test_code\"}";
|
|
||||
//
|
|
||||
// for (int i = 1; i <= 3; i++) {
|
|
||||
// System.out.println("========== 第 " + i + " 次调用深i企登录 ==========");
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
// System.out.println("第 " + i + " 次调用响应: " + responseBody);
|
|
||||
//
|
|
||||
// Thread.sleep(1000);
|
|
||||
// }
|
|
||||
//
|
|
||||
// System.out.println("========== 重复登录测试完成 ==========");
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 验证 Token 格式")
|
|
||||
// @Test
|
|
||||
// @Order(7)
|
|
||||
// public void testSiqLoginTokenFormat() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"test_code\"}";
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
//
|
|
||||
// if (responseBody.contains("\"code\":200")) {
|
|
||||
// String token = extractTokenFromResponse(responseBody);
|
|
||||
// if (token != null && !token.isEmpty()) {
|
|
||||
// Assertions.assertTrue(token.length() > 10, "Token 长度应大于10个字符");
|
|
||||
// System.out.println("Token 格式验证通过,Token: " + token);
|
|
||||
// } else {
|
|
||||
// System.out.println("未能提取到 Token");
|
|
||||
// }
|
|
||||
// } else {
|
|
||||
// System.out.println("登录失败,无法验证 Token 格式");
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// @DisplayName("深i企登录 - 验证企业信息关联")
|
|
||||
// @Test
|
|
||||
// @Order(8)
|
|
||||
// public void testSiqLoginEnterpriseAssociation() throws Exception {
|
|
||||
// String requestBody = "{\"code\":\"test_code\"}";
|
|
||||
//
|
|
||||
// MvcResult result = mockMvc.perform(post(BASE_URL + "/siqLogin")
|
|
||||
// .contentType(MediaType.APPLICATION_JSON)
|
|
||||
// .content(requestBody))
|
|
||||
// .andDo(print())
|
|
||||
// .andExpect(status().isOk())
|
|
||||
// .andReturn();
|
|
||||
//
|
|
||||
// String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
|
||||
//
|
|
||||
// if (responseBody.contains("\"code\":200")) {
|
|
||||
// String data = extractDataJson(responseBody);
|
|
||||
// if (data != null) {
|
|
||||
// String enterpriseId = extractJsonValue(data, "enterpriseId");
|
|
||||
// String enterpriseName = extractJsonValue(data, "enterpriseName");
|
|
||||
// String enterpriseNumber = extractJsonValue(data, "enterpriseNumber");
|
|
||||
//
|
|
||||
// if (enterpriseId != null && enterpriseName != null && enterpriseNumber != null) {
|
|
||||
// Assertions.assertFalse(enterpriseId.isEmpty(), "企业ID不应为空");
|
|
||||
// Assertions.assertFalse(enterpriseName.isEmpty(), "企业名称不应为空");
|
|
||||
// Assertions.assertFalse(enterpriseNumber.isEmpty(), "企业统一信用代码不应为空");
|
|
||||
// System.out.println("企业信息关联验证通过");
|
|
||||
// System.out.println("企业ID: " + enterpriseId);
|
|
||||
// System.out.println("企业名称: " + enterpriseName);
|
|
||||
// System.out.println("企业统一信用代码: " + enterpriseNumber);
|
|
||||
// }
|
|
||||
// }
|
|
||||
// } else {
|
|
||||
// System.out.println("登录失败,无法验证企业信息关联");
|
|
||||
// }
|
|
||||
// }
|
|
||||
//
|
|
||||
// // ==================== 工具方法 ====================
|
|
||||
//
|
|
||||
// /**
|
|
||||
// * 从 JSON 响应中提取 data 字段
|
|
||||
// */
|
|
||||
// private String extractDataJson(String responseBody) {
|
|
||||
// if (responseBody != null && responseBody.contains("\"data\":{")) {
|
|
||||
// int start = responseBody.indexOf("\"data\":{") + 7;
|
|
||||
// int end = responseBody.lastIndexOf("}");
|
|
||||
// if (start > 0 && end > start) {
|
|
||||
// return responseBody.substring(start, end + 1);
|
|
||||
// }
|
|
||||
// }
|
|
||||
// return null;
|
|
||||
// }
|
|
||||
//
|
|
||||
// /**
|
|
||||
// * 从响应中提取 Token
|
|
||||
// */
|
|
||||
// private String extractTokenFromResponse(String responseBody) {
|
|
||||
// return extractJsonValue(responseBody, "token");
|
|
||||
// }
|
|
||||
//
|
|
||||
// /**
|
|
||||
// * 从 JSON 字符串中提取指定字段的值
|
|
||||
// */
|
|
||||
// private String extractJsonValue(String json, String key) {
|
|
||||
// if (json != null && json.contains("\"" + key + "\"")) {
|
|
||||
// int start = json.indexOf("\"" + key + "\":\"") + key.length() + 4;
|
|
||||
// int end = json.indexOf("\"", start);
|
|
||||
// if (start > 0 && end > start) {
|
|
||||
// return json.substring(start, end);
|
|
||||
// }
|
|
||||
// }
|
|
||||
// return null;
|
|
||||
// }
|
|
||||
//}
|
|
||||
//{
|
|
||||
//}
|
|
||||
@ -1,329 +0,0 @@ |
|||||
package com.zdxt.rest.test.cp; |
|
||||
|
|
||||
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil; |
|
||||
import cn.dev33.satoken.stp.StpUtil; |
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
|
||||
import com.fasterxml.jackson.databind.JsonNode; |
|
||||
import com.fasterxml.jackson.databind.ObjectMapper; |
|
||||
import com.zdxt.enforcementcode.domain.bo.EnterpriseInformationBo; |
|
||||
import com.zdxt.enforcementcode.domain.vo.EnterpriseInformationVo; |
|
||||
import com.zdxt.enforcementcode.service.IEnterpriseInformationService; |
|
||||
import org.dromara.ZdxtAdminApplication; |
|
||||
import org.dromara.common.core.domain.model.LoginUser; |
|
||||
import org.dromara.common.satoken.utils.LoginHelper; |
|
||||
import org.junit.jupiter.api.*; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; |
|
||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||
import org.springframework.http.MediaType; |
|
||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||
import org.springframework.test.context.ActiveProfiles; |
|
||||
import org.springframework.test.web.servlet.MockMvc; |
|
||||
import org.springframework.test.web.servlet.MvcResult; |
|
||||
import org.springframework.web.context.request.RequestContextHolder; |
|
||||
import org.springframework.web.context.request.ServletRequestAttributes; |
|
||||
|
|
||||
import javax.crypto.Cipher; |
|
||||
import javax.crypto.spec.IvParameterSpec; |
|
||||
import javax.crypto.spec.SecretKeySpec; |
|
||||
import java.nio.charset.StandardCharsets; |
|
||||
import java.text.SimpleDateFormat; |
|
||||
import java.util.*; |
|
||||
|
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; |
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; |
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; |
|
||||
|
|
||||
/** |
|
||||
* AppEnfCpPlanController 新增计划批量测试 |
|
||||
* <p> |
|
||||
* 为多个用户批量创建执法计划(每人100条) |
|
||||
* </p> |
|
||||
*/ |
|
||||
@SpringBootTest(classes = ZdxtAdminApplication.class) |
|
||||
@AutoConfigureMockMvc |
|
||||
@ActiveProfiles({"dev", "dev-cust-zrb"}) |
|
||||
@DisplayName("AppEnfCpPlanController 批量新增计划测试") |
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class) |
|
||||
public class AppEnfCpPlanControllerTest { |
|
||||
|
|
||||
@Autowired |
|
||||
private MockMvc mockMvc; |
|
||||
|
|
||||
@Autowired |
|
||||
private ObjectMapper objectMapper; |
|
||||
|
|
||||
@Autowired |
|
||||
private IEnterpriseInformationService enterpriseInformationService; |
|
||||
|
|
||||
private static final String BASE_URL = "/app-enf/cpPlan"; |
|
||||
private static final String LOGIN_URL = "/app-enf/login/do"; |
|
||||
private static final String AES_KEY = "1234567898745621"; |
|
||||
private static final String CLIENT_ID = "f0535c2a32ab4d0496ab9a699b2a7d36"; |
|
||||
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"; |
|
||||
|
|
||||
/** 通用密码 */ |
|
||||
private static final String PASSWORD = "szsf@zfjd"; |
|
||||
|
|
||||
@BeforeEach |
|
||||
public void setUp() { |
|
||||
// 初始化 Sa-Token 上下文
|
|
||||
SaTokenContextMockUtil.setMockContext(); |
|
||||
MockHttpServletRequest mockRequest = new MockHttpServletRequest(); |
|
||||
mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); |
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest)); |
|
||||
} |
|
||||
|
|
||||
@AfterEach |
|
||||
public void tearDown() { |
|
||||
try { |
|
||||
StpUtil.logout(); |
|
||||
} catch (Exception ignored) { |
|
||||
} |
|
||||
RequestContextHolder.resetRequestAttributes(); |
|
||||
SaTokenContextMockUtil.clearContext(); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 登录指定账号,返回登录信息 |
|
||||
*/ |
|
||||
private Map<String, String> doLogin(String account) throws Exception { |
|
||||
String encryptedPassword = encryptByAes(PASSWORD); |
|
||||
Map<String, String> loginParams = new HashMap<>(); |
|
||||
loginParams.put("secretName", account); |
|
||||
loginParams.put("secretKey", encryptedPassword); |
|
||||
|
|
||||
MvcResult loginResult = mockMvc.perform(post(LOGIN_URL) |
|
||||
.header("User-Agent", USER_AGENT) |
|
||||
.contentType(MediaType.APPLICATION_JSON) |
|
||||
.content(objectMapper.writeValueAsString(loginParams))) |
|
||||
.andExpect(status().isOk()) |
|
||||
.andExpect(jsonPath("$.code").value(200)) |
|
||||
.andReturn(); |
|
||||
|
|
||||
String loginBody = loginResult.getResponse().getContentAsString(StandardCharsets.UTF_8); |
|
||||
JsonNode loginJson = objectMapper.readTree(loginBody); |
|
||||
JsonNode data = loginJson.get("data"); |
|
||||
|
|
||||
Map<String, String> info = new HashMap<>(); |
|
||||
info.put("token", data.get("token").asText()); |
|
||||
info.put("userId", data.get("userId").asText()); |
|
||||
// nickName 可能为空,回退到 userName(中文姓名)
|
|
||||
String nickName = data.has("nickName") ? data.get("nickName").asText() : ""; |
|
||||
if (nickName == null || nickName.isBlank()) { |
|
||||
nickName = data.has("userName") ? data.get("userName").asText() : account; |
|
||||
} |
|
||||
info.put("nickName", nickName); |
|
||||
info.put("deptId", data.get("deptId").asText()); |
|
||||
info.put("deptName", data.get("deptName").asText()); |
|
||||
info.put("organId", data.get("organId").asText()); |
|
||||
info.put("organName", data.get("organName").asText()); |
|
||||
info.put("bureauUnitId", data.get("bureauUnitId").asText()); |
|
||||
info.put("bureauUnitName", data.get("bureauUnitName").asText()); |
|
||||
info.put("phonenumber", data.has("phonenumber") ? data.get("phonenumber").asText() : ""); |
|
||||
|
|
||||
System.out.println("[" + account + "] 登录成功: userId=" + info.get("userId")); |
|
||||
return info; |
|
||||
} |
|
||||
|
|
||||
// ==================== 各账号批量新增测试 ====================
|
|
||||
|
|
||||
@DisplayName("liuqianlin(刘倩琳)批量新增100条执法计划") |
|
||||
@Test |
|
||||
@Order(1) |
|
||||
public void testBatchCreate_liuqianlin() throws Exception { |
|
||||
batchCreatePlans("liuqianlin", 100); |
|
||||
} |
|
||||
|
|
||||
@DisplayName("baining(白宁)批量新增100条执法计划") |
|
||||
@Test |
|
||||
@Order(2) |
|
||||
public void testBatchCreate_baining() throws Exception { |
|
||||
batchCreatePlans("baining", 100); |
|
||||
} |
|
||||
|
|
||||
@DisplayName("caizifan(蔡梓帆)批量新增100条执法计划") |
|
||||
@Test |
|
||||
@Order(3) |
|
||||
public void testBatchCreate_caizifan() throws Exception { |
|
||||
batchCreatePlans("caizifan", 100); |
|
||||
} |
|
||||
|
|
||||
@DisplayName("chenchong4(陈冲)批量新增100条执法计划") |
|
||||
@Test |
|
||||
@Order(4) |
|
||||
public void testBatchCreate_chenchong4() throws Exception { |
|
||||
batchCreatePlans("chenchong4", 100); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 为指定账号批量新增计划 |
|
||||
* <p> |
|
||||
* 唯一性约束:同一人 + 日期 + 时间段 + 企业 只能有一条计划。 |
|
||||
* 日期循环31天(7月1~31日),时间段2个(上午/下午),企业循环7家, |
|
||||
* 因 31、2、7 两两互素,由中国剩余定理(CRT)保证前 31×2×7=434 条组合均唯一, |
|
||||
* 故 count≤434 时所有计划不会重复。 |
|
||||
* </p> |
|
||||
*/ |
|
||||
private void batchCreatePlans(String account, int count) throws Exception { |
|
||||
Map<String, String> loginInfo = doLogin(account); |
|
||||
String token = loginInfo.get("token"); |
|
||||
String userId = loginInfo.get("userId"); |
|
||||
String nickName = loginInfo.get("nickName"); |
|
||||
|
|
||||
// 从数据库加载指定企业列表
|
|
||||
List<EnterpriseInformationVo> enterprises = loadEnterprises(); |
|
||||
Assertions.assertFalse(enterprises.isEmpty(), "数据库中无可用企业数据"); |
|
||||
|
|
||||
// --- 唯一性预测验证 ---
|
|
||||
int days = 31; // 7月有31天
|
|
||||
int timeSlots = 2; // 上午/下午
|
|
||||
int entCount = enterprises.size(); |
|
||||
// 由CRT保证的最大不重复组合数 = lcm(days, timeSlots, entCount) 当两两互素时 = days * timeSlots * entCount
|
|
||||
int maxUnique = days * timeSlots * entCount; |
|
||||
int expectedSuccess = Math.min(count, maxUnique); |
|
||||
System.out.println("[" + account + "] 企业数=" + entCount |
|
||||
+ ", 可用唯一组合(日期×时段×企业)=" + maxUnique |
|
||||
+ ", 计划生成数=" + count |
|
||||
+ ", 预计成功数=" + expectedSuccess); |
|
||||
Assertions.assertTrue(count <= maxUnique, |
|
||||
"计划数(" + count + ")超过最大唯一组合数(" + maxUnique + "),必然产生重复"); |
|
||||
|
|
||||
Random random = new Random(); |
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); |
|
||||
Calendar cal = Calendar.getInstance(); |
|
||||
|
|
||||
int successCount = 0; |
|
||||
int failCount = 0; |
|
||||
|
|
||||
for (int i = 0; i < count; i++) { |
|
||||
// 所有计划日期限定在2026年7月内,循环使用7月1日~31日
|
|
||||
int dayOfMonth = (i % days) + 1; |
|
||||
cal.set(2026, Calendar.JULY, dayOfMonth); |
|
||||
String planDate = sdf.format(cal.getTime()); |
|
||||
long planTime = (i % 2 == 0) ? 1L : 2L; // 交替上午/下午
|
|
||||
|
|
||||
// 确定性循环选取企业,保证 (日期, 时段, 企业) 三元组唯一
|
|
||||
EnterpriseInformationVo enterprise = enterprises.get(i % entCount); |
|
||||
Map<String, Object> planBo = buildPlanBo(planDate, planTime, i, nickName, userId, loginInfo, enterprise, random); |
|
||||
String requestBody = objectMapper.writeValueAsString(planBo); |
|
||||
|
|
||||
MvcResult result = mockMvc.perform(post(BASE_URL) |
|
||||
.header("Authorization", "Bearer " + token) |
|
||||
.header("clientid", CLIENT_ID) |
|
||||
.header("User-Agent", USER_AGENT) |
|
||||
.contentType(MediaType.APPLICATION_JSON) |
|
||||
.content(requestBody)) |
|
||||
.andReturn(); |
|
||||
|
|
||||
String responseBody = result.getResponse().getContentAsString(StandardCharsets.UTF_8); |
|
||||
JsonNode respJson = objectMapper.readTree(responseBody); |
|
||||
int code = respJson.get("code").asInt(); |
|
||||
|
|
||||
if (code == 200) { |
|
||||
successCount++; |
|
||||
} else { |
|
||||
failCount++; |
|
||||
System.out.println("[" + account + "] 第" + (i + 1) + "条失败: " + responseBody); |
|
||||
} |
|
||||
|
|
||||
if ((i + 1) % 10 == 0) { |
|
||||
System.out.println("[" + account + "] 已处理 " + (i + 1) + "/" + count |
|
||||
+ ", 成功=" + successCount + ", 失败=" + failCount); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
System.out.println("========== [" + account + "] 批量新增完成 =========="); |
|
||||
System.out.println("总计: " + count + ", 成功: " + successCount + ", 失败: " + failCount); |
|
||||
Assertions.assertEquals(expectedSuccess, successCount, |
|
||||
"[" + account + "] 预期成功" + expectedSuccess + "条,实际成功" + successCount + "条"); |
|
||||
} |
|
||||
|
|
||||
/** 指定的企业统一社会信用代码列表 */ |
|
||||
private static final String[][] ENTERPRISE_DATA = { |
|
||||
{"吉田拉链(深圳)有限公司公明工厂", "91440300788302281W"}, |
|
||||
{"欧姆龙电子部件(深圳)有限公司", "914403007261811621"}, |
|
||||
{"深圳农牧美益肉业有限公司", "91440300662678582M"}, |
|
||||
{"深圳市深水龙岗污水处理有限公司", "914403006820066603"}, |
|
||||
{"深圳市强达电路股份有限公司", "91440300763461366N"}, |
|
||||
{"深圳康泰生物制品股份有限公司", "91440300618837873J"}, |
|
||||
{"深圳市里程食品有限公司", "91440300738848091F"}, |
|
||||
}; |
|
||||
|
|
||||
/** |
|
||||
* 从数据库加载指定的7家企业 |
|
||||
*/ |
|
||||
private List<EnterpriseInformationVo> loadEnterprises() { |
|
||||
List<EnterpriseInformationVo> result = new ArrayList<>(); |
|
||||
for (String[] entry : ENTERPRISE_DATA) { |
|
||||
EnterpriseInformationBo queryBo = new EnterpriseInformationBo(); |
|
||||
queryBo.setEnterpriseNumber(entry[1]); |
|
||||
queryBo.setIsDelete(0L); |
|
||||
List<EnterpriseInformationVo> list = enterpriseInformationService.queryList(queryBo); |
|
||||
if (!list.isEmpty()) { |
|
||||
result.add(list.get(0)); |
|
||||
} else { |
|
||||
System.out.println("[警告] 未找到企业: " + entry[0] + " (" + entry[1] + ")"); |
|
||||
} |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* 构建计划BO的Map |
|
||||
*/ |
|
||||
private Map<String, Object> buildPlanBo(String planDate, long planTime, int index, |
|
||||
String userName, String userId, Map<String, String> loginInfo, |
|
||||
EnterpriseInformationVo enterprise, Random random) { |
|
||||
Map<String, Object> bo = new LinkedHashMap<>(); |
|
||||
bo.put("planType", 1L); // 日常计划
|
|
||||
bo.put("planDate", planDate); |
|
||||
bo.put("planTime", planTime); |
|
||||
bo.put("enforceContent", "批量测试执法事项-第" + (index + 1) + "条"); |
|
||||
bo.put("enterpriseName", enterprise.getEnterpriseName()); |
|
||||
bo.put("enterpriseNumber", enterprise.getEnterpriseNumber()); |
|
||||
bo.put("enterpriseId", enterprise.getId()); |
|
||||
bo.put("enforceUserNames", userName); |
|
||||
bo.put("enforceUserIds", userId); |
|
||||
bo.put("enforceUserTels", loginInfo.get("phonenumber")); |
|
||||
bo.put("enforceUserCodes", "-"); |
|
||||
bo.put("isPublic", random.nextInt(2) == 0 ? 0L : 1L); // 随机公开/不公开
|
|
||||
bo.put("isUnion", 1L); // 必须为联合执法,否则afterInsert会直接生成任务导致status变为3
|
|
||||
bo.put("reserveStatus", 1L); // 待预约
|
|
||||
bo.put("systemReserved", 0L); |
|
||||
bo.put("manualReserved", 0L); |
|
||||
bo.put("bureauDeptId", loginInfo.get("bureauUnitId")); |
|
||||
bo.put("bureauDeptName", loginInfo.get("bureauUnitName")); |
|
||||
bo.put("organId", loginInfo.get("organId")); |
|
||||
bo.put("organName", loginInfo.get("organName")); |
|
||||
bo.put("deptId", loginInfo.get("deptId")); |
|
||||
bo.put("deptName", loginInfo.get("deptName")); |
|
||||
bo.put("isDelete", 0L); |
|
||||
return bo; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* AES/CBC/ZeroPadding 加密(与前端 CryptoJS 对应) |
|
||||
*/ |
|
||||
private String encryptByAes(String plainText) throws Exception { |
|
||||
byte[] keyBytes = AES_KEY.getBytes(StandardCharsets.UTF_8); |
|
||||
byte[] ivBytes = AES_KEY.getBytes(StandardCharsets.UTF_8); |
|
||||
|
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(keyBytes, "AES"); |
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes); |
|
||||
|
|
||||
// NoPadding 需要手动补零到16字节倍数
|
|
||||
byte[] plainBytes = plainText.getBytes(StandardCharsets.UTF_8); |
|
||||
int blockSize = 16; |
|
||||
int paddedLen = ((plainBytes.length / blockSize) + 1) * blockSize; |
|
||||
byte[] padded = new byte[paddedLen]; |
|
||||
System.arraycopy(plainBytes, 0, padded, 0, plainBytes.length); |
|
||||
// 剩余字节默认为0(ZeroPadding)
|
|
||||
|
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); |
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec); |
|
||||
byte[] encrypted = cipher.doFinal(padded); |
|
||||
|
|
||||
return Base64.getEncoder().encodeToString(encrypted); |
|
||||
} |
|
||||
} |
|
||||
@ -1,225 +0,0 @@ |
|||||
package com.zdxt.service.test; |
|
||||
|
|
||||
import cn.hutool.crypto.digest.DigestUtil; |
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
|
||||
import com.zdxt.enforcementcode.domain.EnterpriseUser; |
|
||||
import com.zdxt.enforcementcode.mapper.EnterpriseUserMapper; |
|
||||
import org.dromara.ZdxtAdminApplication; |
|
||||
import org.dromara.system.domain.SysUser; |
|
||||
import org.dromara.system.mapper.SysUserMapper; |
|
||||
import org.junit.jupiter.api.DisplayName; |
|
||||
import org.junit.jupiter.api.Test; |
|
||||
import org.springframework.beans.factory.annotation.Autowired; |
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; |
|
||||
import org.springframework.boot.test.context.SpringBootTest; |
|
||||
|
|
||||
import java.util.Arrays; |
|
||||
import java.util.HashSet; |
|
||||
import java.util.List; |
|
||||
|
|
||||
import cn.dev33.satoken.context.mock.SaTokenContextMockUtil; |
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter; |
|
||||
import cn.dev33.satoken.stp.StpUtil; |
|
||||
import org.dromara.common.core.domain.model.LoginUser; |
|
||||
import org.dromara.common.satoken.utils.LoginHelper; |
|
||||
import org.junit.jupiter.api.AfterEach; |
|
||||
import org.junit.jupiter.api.BeforeEach; |
|
||||
import org.springframework.mock.web.MockHttpServletRequest; |
|
||||
import org.springframework.test.context.ActiveProfiles; |
|
||||
import org.springframework.web.context.request.RequestContextHolder; |
|
||||
import org.springframework.web.context.request.ServletRequestAttributes; |
|
||||
|
|
||||
/** |
|
||||
* 批量重置 enterprise_user 表用户密码 |
|
||||
* <p> |
|
||||
* 密码加密规则: MD5(userName + password + salt) |
|
||||
* </p> |
|
||||
*/ |
|
||||
@SpringBootTest(classes = ZdxtAdminApplication.class) |
|
||||
@AutoConfigureMockMvc |
|
||||
@ActiveProfiles({"dev", "dev-cust-zrb"}) |
|
||||
@DisplayName("批量重置企业用户密码") |
|
||||
public class ResetUserPasswordTest { |
|
||||
|
|
||||
@Autowired |
|
||||
private EnterpriseUserMapper enterpriseUserMapper; |
|
||||
|
|
||||
@Autowired |
|
||||
private SysUserMapper sysUserMapper; |
|
||||
|
|
||||
/** 重置后的明文密码 */ |
|
||||
private static final String NEW_PASSWORD = "szsf@zfjd"; |
|
||||
//private static final String NEW_PASSWORD = "Szsf@123";
|
|
||||
|
|
||||
private static final String TEST_CLIENT_ID = "e5cd7e4891bf95d1d19206ce24a7b32e"; |
|
||||
|
|
||||
@BeforeEach |
|
||||
public void setUp() { |
|
||||
// 初始化 Sa-Token 上下文(非 Web 环境下 StpUtil.login 需要)
|
|
||||
SaTokenContextMockUtil.setMockContext(); |
|
||||
|
|
||||
// 设置模拟请求上下文(数据权限拦截器需要从 SaToken 上下文获取用户信息)
|
|
||||
MockHttpServletRequest mockRequest = new MockHttpServletRequest(); |
|
||||
mockRequest.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"); |
|
||||
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest)); |
|
||||
|
|
||||
// 构造测试用登录用户
|
|
||||
LoginUser loginUser = new LoginUser(); |
|
||||
loginUser.setUserId(1L); |
|
||||
loginUser.setUserType("sys_user"); |
|
||||
loginUser.setTenantId("000000"); |
|
||||
loginUser.setUsername("test_admin"); |
|
||||
loginUser.setNickname("测试管理员"); |
|
||||
loginUser.setDeptId("103"); |
|
||||
loginUser.setDeptName("测试部门"); |
|
||||
loginUser.setRolePermission(new HashSet<>()); |
|
||||
loginUser.setMenuPermission(new HashSet<>()); |
|
||||
|
|
||||
// 模拟登录
|
|
||||
SaLoginParameter param = new SaLoginParameter(); |
|
||||
param.setExtra(LoginHelper.CLIENT_KEY, TEST_CLIENT_ID); |
|
||||
LoginHelper.login(loginUser, param); |
|
||||
} |
|
||||
|
|
||||
@AfterEach |
|
||||
public void tearDown() { |
|
||||
try { |
|
||||
StpUtil.logout(); |
|
||||
} catch (Exception ignored) { |
|
||||
} |
|
||||
RequestContextHolder.resetRequestAttributes(); |
|
||||
SaTokenContextMockUtil.clearContext(); |
|
||||
} |
|
||||
|
|
||||
@DisplayName("批量重置 enterprise_user 所有用户密码为 szsf@zfjd") |
|
||||
@Test |
|
||||
public void resetAllEnterpriseUserPassword() { |
|
||||
|
|
||||
/*-- 17608540150,weil45,"",15817307171,深圳农牧美益肉业有限公司,91440300662678582M,21 |
|
||||
-- 17608557492,DGD440881199506180622,"",15817381630,深圳市深水龙岗污水处理有限公司,914403006820066603,12 |
|
||||
-- 17608540121,smiledzb1982,"",13723454151,深圳康泰生物制品股份有限公司,91440300618837873J,10 |
|
||||
-- 17608594890,A7271888,"",13751661770,深圳市里程食品有限公司,91440300738848091F,9 |
|
||||
-- 17608565612,qintongzhen138,"",13823610579,欧姆龙电子部件(深圳)有限公司,914403007261811621,9 |
|
||||
-- 17608601734,XP073215,"",15012671807,深圳市强达电路股份有限公司,91440300763461366N,9 |
|
||||
-- 17608556724,33ef1970fd449676fa4bc197,"",13537602265,吉田拉链(深圳)有限公司公明工厂,91440300788302281W,8*/ |
|
||||
|
|
||||
// 1. 指定需要重置密码的用户ID列表
|
|
||||
List<String> userIds = Arrays.asList( |
|
||||
// TODO: 在此填入需要重置的用户ID
|
|
||||
"17608540150", "17608557492", "17608540121", "17608594890", "17608565612", "17608601734", "17608556724","2064275054386966530","2064274295779979265","17608629742" |
|
||||
); |
|
||||
|
|
||||
// 2. 根据ID列表查询企业用户
|
|
||||
List<EnterpriseUser> userList = enterpriseUserMapper.selectList( |
|
||||
new LambdaQueryWrapper<EnterpriseUser>() |
|
||||
.select(EnterpriseUser::getUserId, EnterpriseUser::getLoginName, EnterpriseUser::getUserName, EnterpriseUser::getSalt) |
|
||||
.in(EnterpriseUser::getUserId, userIds) |
|
||||
); |
|
||||
|
|
||||
System.out.println("查询到企业用户总数: " + userList.size()); |
|
||||
|
|
||||
int successCount = 0; |
|
||||
int skipCount = 0; |
|
||||
|
|
||||
for (EnterpriseUser user : userList) { |
|
||||
String loginName = user.getLoginName(); |
|
||||
String salt = user.getSalt(); |
|
||||
|
|
||||
if (loginName == null || loginName.isBlank()) { |
|
||||
System.out.println("跳过: userId=" + user.getUserId() + ", loginName为空"); |
|
||||
skipCount++; |
|
||||
continue; |
|
||||
} |
|
||||
if (salt == null || salt.isBlank()) { |
|
||||
System.out.println("跳过: userId=" + user.getUserId() + ", salt为空"); |
|
||||
skipCount++; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// 3. 按规则生成新密码: MD5(loginName + newPassword + salt)
|
|
||||
String newMd5Password = DigestUtil.md5Hex(loginName + NEW_PASSWORD + salt); |
|
||||
|
|
||||
// 4. 更新密码
|
|
||||
int rows = enterpriseUserMapper.update(null, |
|
||||
new LambdaUpdateWrapper<EnterpriseUser>() |
|
||||
.eq(EnterpriseUser::getUserId, user.getUserId()) |
|
||||
.set(EnterpriseUser::getPassword, newMd5Password) |
|
||||
); |
|
||||
|
|
||||
if (rows > 0) { |
|
||||
successCount++; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
System.out.println("========== 重置完成 =========="); |
|
||||
System.out.println("成功: " + successCount + " 条"); |
|
||||
System.out.println("跳过: " + skipCount + " 条"); |
|
||||
System.out.println("新密码(明文): " + NEW_PASSWORD); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
@DisplayName("批量重置 sys_user 指定用户密码为 szsf@zfjd") |
|
||||
@Test |
|
||||
public void resetSysUserPassword() { |
|
||||
// 1. 执法端的测试用户
|
|
||||
List<Long> userIds = Arrays.asList( |
|
||||
// TODO: 在此填入需要重置的用户ID
|
|
||||
7897L, 17608416858L,17608416876L, 17608416904L,17608416912L, 17608416926L,17608416927L, 17608416945L,17608417058L,17608642193L,17608502852L,17608515249L,17608497168L |
|
||||
); |
|
||||
|
|
||||
// 监督端的报表测试用户
|
|
||||
// userIds = Arrays.asList(
|
|
||||
// // TODO: 在此填入需要重置的用户ID
|
|
||||
// 17608417340L, 17608417451L,17608417716L, 17608614169L,17608614499L,7897L,17608634290L
|
|
||||
// );
|
|
||||
|
|
||||
// 2. 根据ID列表查询系统用户
|
|
||||
List<SysUser> userList = sysUserMapper.selectList( |
|
||||
new LambdaQueryWrapper<SysUser>() |
|
||||
.select(SysUser::getUserId, SysUser::getLoginName, SysUser::getSalt) |
|
||||
.in(SysUser::getUserId, userIds) |
|
||||
); |
|
||||
|
|
||||
System.out.println("查询到系统用户总数: " + userList.size()); |
|
||||
|
|
||||
int successCount = 0; |
|
||||
int skipCount = 0; |
|
||||
|
|
||||
for (SysUser user : userList) { |
|
||||
String loginName = user.getLoginName(); |
|
||||
String salt = user.getSalt(); |
|
||||
|
|
||||
if (loginName == null || loginName.isBlank()) { |
|
||||
System.out.println("跳过: userId=" + user.getUserId() + ", loginName为空"); |
|
||||
skipCount++; |
|
||||
continue; |
|
||||
} |
|
||||
if (salt == null || salt.isBlank()) { |
|
||||
System.out.println("跳过: userId=" + user.getUserId() + ", salt为空"); |
|
||||
skipCount++; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// 3. 按规则生成新密码: MD5( + newPassword + salt)
|
|
||||
String newMd5Password = DigestUtil.md5Hex(loginName + NEW_PASSWORD + salt); |
|
||||
|
|
||||
// 4. 更新密码
|
|
||||
int rows = sysUserMapper.update(null, |
|
||||
new LambdaUpdateWrapper<SysUser>() |
|
||||
.eq(SysUser::getUserId, user.getUserId()) |
|
||||
.set(SysUser::getPassword, newMd5Password) |
|
||||
); |
|
||||
|
|
||||
if (rows > 0) { |
|
||||
successCount++; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
System.out.println("========== sys_user 重置完成 =========="); |
|
||||
System.out.println("成功: " + successCount + " 条"); |
|
||||
System.out.println("跳过: " + skipCount + " 条"); |
|
||||
System.out.println("新密码(明文): " + NEW_PASSWORD); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
Loading…
Reference in new issue