161 lines
6.1 KiB
Java
161 lines
6.1 KiB
Java
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<Map> 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<String, Object> data = (Map<String, Object>) 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<Map> response = doLogin("DEMO", "admin", "wrong_password");
|
||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||
}
|
||
|
||
@Test
|
||
@DisplayName("不存在的公司代码 → 401 Unauthorized")
|
||
void login_withUnknownCompany_returns401() {
|
||
ResponseEntity<Map> 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<Map> response = restTemplate.exchange(
|
||
baseUrl("/api/auth/me"),
|
||
HttpMethod.GET,
|
||
bearerRequest(token),
|
||
Map.class);
|
||
|
||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||
|
||
@SuppressWarnings("unchecked")
|
||
Map<String, Object> data = (Map<String, Object>) 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<String> 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<Map> meResponse = restTemplate.exchange(
|
||
baseUrl("/api/auth/me"),
|
||
HttpMethod.GET,
|
||
bearerRequest(token),
|
||
Map.class);
|
||
assertThat(meResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||
|
||
// 退出
|
||
ResponseEntity<Map> logoutResponse = restTemplate.exchange(
|
||
baseUrl("/api/auth/logout"),
|
||
HttpMethod.POST,
|
||
bearerRequest(token),
|
||
Map.class);
|
||
assertThat(logoutResponse.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||
|
||
// 退出后再访问 /me → 401
|
||
ResponseEntity<Map> meAfterLogout = restTemplate.exchange(
|
||
baseUrl("/api/auth/me"),
|
||
HttpMethod.GET,
|
||
bearerRequest(token),
|
||
Map.class);
|
||
assertThat(meAfterLogout.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
|
||
}
|
||
|
||
// ------------------------------------------------------------------ 工具方法 --
|
||
|
||
/** 发起登录请求,返回原始 ResponseEntity */
|
||
private ResponseEntity<Map> 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<Map> response = doLogin(companyCode, username, password);
|
||
if (!response.getStatusCode().is2xxSuccessful()) {
|
||
return null;
|
||
}
|
||
@SuppressWarnings("unchecked")
|
||
Map<String, Object> data = (Map<String, Object>) response.getBody().get("data");
|
||
return (String) data.get("token");
|
||
}
|
||
|
||
/** 构造带 Bearer Token 的请求实体(无 body) */
|
||
private HttpEntity<Void> bearerRequest(String token) {
|
||
HttpHeaders headers = new HttpHeaders();
|
||
headers.set("Authorization", "Bearer " + token);
|
||
return new HttpEntity<>(headers);
|
||
}
|
||
}
|