package com.xuekairui.gateway; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; 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 static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * B2B平台账号绑定全流程测试 * * 测试场景: * 1. 绑定药师帮账号 * 2. 查询已绑定列表 * 3. 验证账号 * 4. 解绑账号 * 5. 异常场景测试 */ @SpringBootTest @AutoConfigureMockMvc @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @Slf4j public class PlatformAccountBindingTest extends GatewayBaseTest { @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; private String accessToken; private Long userId; /** * 前置条件:先登录获取Token */ @BeforeEach public void setUp() throws Exception { // 登录获取Token MvcResult result = mockMvc.perform(post("/api/auth/sms/login") .contentType(MediaType.APPLICATION_JSON) .content("{\"phone\":\"13800138000\",\"code\":\"123456\"}")) .andExpect(status().isOk()) .andReturn(); String response = result.getResponse().getContentAsString(); accessToken = objectMapper.readTree(response).get("data").get("accessToken").asText(); userId = objectMapper.readTree(response).get("data").get("userId").asLong(); log.info("🔑 登录成功: userId={}", userId); } /** * 测试1:绑定药师帮账号 */ @Test @Order(1) @DisplayName("1. 绑定药师帮账号") public void testBindYaoshibangAccount() throws Exception { mockMvc.perform(post("/api/platform-account/bind") .header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(new Object() { public String platformCode = "yaoshibang"; public String platformName = "药师帮"; public String account = "13800138000"; public String password = "test_password_123"; }))) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.message").value("操作成功")); log.info("✅ 绑定药师帮账号成功"); } /** * 测试2:绑定药帮忙账号 */ @Test @Order(2) @DisplayName("2. 绑定药帮忙账号") public void testBindYaobangmangAccount() throws Exception { mockMvc.perform(post("/api/platform-account/bind") .header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(new Object() { public String platformCode = "yaobangmang"; public String platformName = "药帮忙"; public String account = "13900139000"; public String password = "test_password_456"; }))) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)); log.info("✅ 绑定药帮忙账号成功"); } /** * 测试3:查询已绑定平台列表 */ @Test @Order(3) @DisplayName("3. 查询已绑定平台列表") public void testGetBoundAccounts() throws Exception { mockMvc.perform(get("/api/platform-account/list") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isArray()) .andExpect(jsonPath("$.data.length()").value(2)) // 已绑定2个平台 .andExpect(jsonPath("$.data[0].platformCode").exists()) .andExpect(jsonPath("$.data[0].account").exists()) .andExpect(jsonPath("$.data[0].verifyStatus").exists()); log.info("✅ 查询已绑定平台列表成功"); } /** * 测试4:验证平台账号 */ @Test @Order(4) @DisplayName("4. 验证药师帮账号") public void testVerifyAccount() throws Exception { mockMvc.perform(post("/api/platform-account/verify/yaoshibang") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)); log.info("✅ 验证药师帮账号成功"); } /** * 测试5:更新已绑定的账号 */ @Test @Order(5) @DisplayName("5. 更新药师帮账号(重新绑定)") public void testUpdateBoundAccount() throws Exception { mockMvc.perform(post("/api/platform-account/bind") .header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(new Object() { public String platformCode = "yaoshibang"; public String platformName = "药师帮"; public String account = "13800138000"; public String password = "new_password_789"; // 新密码 }))) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)); log.info("✅ 更新药师帮账号成功"); } /** * 测试6:解绑平台账号 */ @Test @Order(6) @DisplayName("6. 解绑药帮忙账号") public void testUnbindAccount() throws Exception { mockMvc.perform(delete("/api/platform-account/unbind/yaobangmang") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)); // 验证解绑后只剩1个平台 mockMvc.perform(get("/api/platform-account/list") .header("Authorization", "Bearer " + accessToken)) .andExpect(jsonPath("$.data.length()").value(1)); log.info("✅ 解绑药帮忙账号成功"); } /** * 测试7:异常场景 - 绑定不存在的平台 */ @Test @Order(7) @DisplayName("7. 异常场景:绑定不支持的平台") public void testBindUnsupportedPlatform() throws Exception { mockMvc.perform(post("/api/platform-account/bind") .header("Authorization", "Bearer " + accessToken) .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(new Object() { public String platformCode = "unsupported_platform"; public String platformName = "不支持的平台"; public String account = "13800138000"; public String password = "password"; }))) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").isNumber()); // 业务错误码 log.info("✅ 不支持的平台拦截正确"); } /** * 测试8:异常场景 - 验证未绑定的平台 */ @Test @Order(8) @DisplayName("8. 异常场景:验证未绑定的平台") public void testVerifyUnboundPlatform() throws Exception { mockMvc.perform(post("/api/platform-account/verify/yiyaocheng") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(400)); log.info("✅ 未绑定平台验证返回业务错误"); } /** * 测试9:异常场景 - 解绑未绑定的平台 */ @Test @Order(9) @DisplayName("9. 异常场景:解绑未绑定的平台") public void testUnbindUnboundPlatform() throws Exception { mockMvc.perform(delete("/api/platform-account/unbind/yiyaocheng") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(400)); log.info("✅ 未绑定平台解绑拦截正确"); } /** * 测试10:账号脱敏验证 */ @Test @Order(10) @DisplayName("10. 验证账号脱敏显示") public void testAccountMasking() throws Exception { MvcResult result = mockMvc.perform(get("/api/platform-account/list") .header("Authorization", "Bearer " + accessToken)) .andExpect(status().isOk()) .andReturn(); String response = result.getResponse().getContentAsString(); String account = objectMapper.readTree(response) .get("data").get(0).get("account").asText(); // 验证账号已脱敏:138****8000 Assertions.assertTrue(account.contains("****"), "账号应该脱敏显示"); Assertions.assertFalse(account.equals("13800138000"), "账号不应明文显示"); log.info("✅ 账号脱敏验证通过: {}", account); } }