package com.label.integration; import com.label.AbstractIntegrationTest; import com.label.common.result.Result; import com.label.module.user.dto.LoginRequest; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; /** * 认证流程集成测试(US1)。 * * 测试场景: * 1. 正确密码登录 → 返回 token * 2. 错误密码登录 → 401 * 3. 不存在的公司代码 → 401 * 4. 有效 Token 访问 /api/auth/me → 200,返回用户信息 * 5. 主动退出后,原 Token 访问 /api/auth/me → 401 * * 测试数据来自 init.sql 种子(DEMO 公司 / admin / admin123) */ public class AuthIntegrationTest extends AbstractIntegrationTest { @Autowired private TestRestTemplate restTemplate; // ------------------------------------------------------------------ 登录测试 -- @Test @DisplayName("正确密码登录 → 返回 token") void login_withCorrectCredentials_returnsToken() { ResponseEntity response = doLogin("DEMO", "admin", "admin123"); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); Map body = response.getBody(); assertThat(body).isNotNull(); assertThat(body.get("code")).isEqualTo("SUCCESS"); @SuppressWarnings("unchecked") Map data = (Map) body.get("data"); assertThat(data.get("token")).isNotNull().isInstanceOf(String.class); assertThat((String) data.get("token")).isNotBlank(); assertThat(data.get("role")).isEqualTo("ADMIN"); } @Test @DisplayName("错误密码登录 → 401 Unauthorized") void login_withWrongPassword_returns401() { ResponseEntity response = doLogin("DEMO", "admin", "wrong_password"); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } @Test @DisplayName("不存在的公司代码 → 401 Unauthorized") void login_withUnknownCompany_returns401() { ResponseEntity response = doLogin("NONEXIST", "admin", "admin123"); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } // ------------------------------------------------------------------ /me 测试 -- @Test @DisplayName("有效 Token 访问 /api/auth/me → 200,返回用户信息") void me_withValidToken_returns200WithUserInfo() { String token = loginAndGetToken("DEMO", "admin", "admin123"); assertThat(token).isNotBlank(); ResponseEntity response = restTemplate.exchange( baseUrl("/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); @SuppressWarnings("unchecked") Map data = (Map) response.getBody().get("data"); assertThat(data.get("username")).isEqualTo("admin"); assertThat(data.get("role")).isEqualTo("ADMIN"); assertThat(data.get("companyId")).isNotNull(); } @Test @DisplayName("无 Token 访问 /api/auth/me → 401") void me_withNoToken_returns401() { ResponseEntity response = restTemplate.getForEntity( baseUrl("/api/auth/me"), String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } // ------------------------------------------------------------------ 退出测试 -- @Test @DisplayName("主动退出后,原 Token 访问 /api/auth/me → 401") void logout_thenMe_returns401() { String token = loginAndGetToken("DEMO", "admin", "admin123"); assertThat(token).isNotBlank(); // 确认登录有效 ResponseEntity meResponse = restTemplate.exchange( baseUrl("/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); assertThat(meResponse.getStatusCode()).isEqualTo(HttpStatus.OK); // 退出 ResponseEntity logoutResponse = restTemplate.exchange( baseUrl("/api/auth/logout"), HttpMethod.POST, bearerRequest(token), Map.class); assertThat(logoutResponse.getStatusCode()).isEqualTo(HttpStatus.OK); // 退出后再访问 /me → 401 ResponseEntity meAfterLogout = restTemplate.exchange( baseUrl("/api/auth/me"), HttpMethod.GET, bearerRequest(token), Map.class); assertThat(meAfterLogout.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); } // ------------------------------------------------------------------ 工具方法 -- /** 发起登录请求,返回原始 ResponseEntity */ private ResponseEntity doLogin(String companyCode, String username, String password) { LoginRequest req = new LoginRequest(); req.setCompanyCode(companyCode); req.setUsername(username); req.setPassword(password); return restTemplate.postForEntity(baseUrl("/api/auth/login"), req, Map.class); } /** 登录并提取 token 字符串;失败时返回 null */ private String loginAndGetToken(String companyCode, String username, String password) { ResponseEntity response = doLogin(companyCode, username, password); if (!response.getStatusCode().is2xxSuccessful()) { return null; } @SuppressWarnings("unchecked") Map data = (Map) response.getBody().get("data"); return (String) data.get("token"); } /** 构造带 Bearer Token 的请求实体(无 body) */ private HttpEntity bearerRequest(String token) { HttpHeaders headers = new HttpHeaders(); headers.set("Authorization", "Bearer " + token); return new HttpEntity<>(headers); } }