package com.rongyichuang.judge;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import org.junit.jupiter.api.Test;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.server.LocalServerPort;
|
import org.springframework.http.HttpEntity;
|
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.MediaType;
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import javax.sql.DataSource;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Map;
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
/**
|
* 评委模块端到端集成测试
|
* 模拟完整的前端到后端数据流程:
|
* 1. 前端获取标签列表
|
* 2. 前端提交评委数据(包含logo.jpg头像)
|
* 3. 后端保存数据到数据库
|
* 4. 验证数据完整性
|
*/
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
public class JudgeE2EIntegrationTest {
|
|
@LocalServerPort
|
private int port;
|
|
@Autowired
|
private TestRestTemplate restTemplate;
|
|
@Autowired
|
private DataSource dataSource;
|
|
private JdbcTemplate jdbcTemplate;
|
private ObjectMapper objectMapper = new ObjectMapper();
|
|
@Test
|
void testCompleteJudgeCreationFlow() throws Exception {
|
jdbcTemplate = new JdbcTemplate(dataSource);
|
|
System.out.println("=== 开始完整的评委创建流程测试 ===");
|
|
// 步骤1: 前端获取可用标签列表
|
System.out.println("\n步骤1: 获取标签列表");
|
List<Map<String, Object>> availableTags = getAvailableTags();
|
assertTrue(availableTags.size() > 0, "应该有可用的标签");
|
System.out.println("✓ 获取到 " + availableTags.size() + " 个标签");
|
|
// 步骤2: 模拟前端上传logo.jpg并获取媒体ID
|
System.out.println("\n步骤2: 上传头像图片");
|
String mediaId = uploadAvatarImage();
|
assertNotNull(mediaId, "媒体ID不应为空");
|
System.out.println("✓ 头像上传成功,媒体ID: " + mediaId);
|
|
// 步骤3: 前端提交评委数据
|
System.out.println("\n步骤3: 创建评委");
|
String judgeId = createJudgeWithAvatar(mediaId, availableTags);
|
assertNotNull(judgeId, "评委ID不应为空");
|
System.out.println("✓ 评委创建成功,ID: " + judgeId);
|
|
// 步骤4: 验证数据库中的数据完整性
|
System.out.println("\n步骤4: 验证数据完整性");
|
verifyJudgeDataIntegrity(judgeId, mediaId);
|
System.out.println("✓ 数据完整性验证通过");
|
|
// 步骤5: 前端查询评委详情
|
System.out.println("\n步骤5: 查询评委详情");
|
Map<String, Object> judgeDetails = getJudgeDetails(judgeId);
|
assertNotNull(judgeDetails, "评委详情不应为空");
|
System.out.println("✓ 评委详情查询成功");
|
|
System.out.println("\n=== 完整流程测试成功 ===");
|
printTestSummary(judgeId, mediaId, judgeDetails);
|
}
|
|
/**
|
* 步骤1: 获取可用标签列表(模拟前端加载标签)
|
*/
|
private List<Map<String, Object>> getAvailableTags() throws Exception {
|
String query = """
|
query {
|
tagsByCategory(category: "major") {
|
id
|
name
|
code
|
}
|
}
|
""";
|
|
Map<String, String> request = Collections.singletonMap("query", query);
|
String response = postGraphQL(request);
|
|
Map<String, Object> responseMap = objectMapper.readValue(response, Map.class);
|
|
// 检查是否有错误
|
if (responseMap.containsKey("errors")) {
|
System.out.println("GraphQL错误: " + responseMap.get("errors"));
|
throw new RuntimeException("GraphQL查询失败: " + responseMap.get("errors"));
|
}
|
|
Map<String, Object> data = (Map<String, Object>) responseMap.get("data");
|
if (data == null) {
|
throw new RuntimeException("GraphQL响应中没有data字段");
|
}
|
|
@SuppressWarnings("unchecked")
|
List<Map<String, Object>> tags = (List<Map<String, Object>>) data.get("tagsByCategory");
|
|
if (tags == null) {
|
// 如果没有专业标签,尝试获取所有标签
|
String allTagsQuery = """
|
query {
|
tags {
|
id
|
name
|
code
|
}
|
}
|
""";
|
|
Map<String, String> allTagsRequest = Collections.singletonMap("query", allTagsQuery);
|
String allTagsResponse = postGraphQL(allTagsRequest);
|
Map<String, Object> allTagsResponseMap = objectMapper.readValue(allTagsResponse, Map.class);
|
Map<String, Object> allTagsData = (Map<String, Object>) allTagsResponseMap.get("data");
|
|
@SuppressWarnings("unchecked")
|
List<Map<String, Object>> allTags = (List<Map<String, Object>>) allTagsData.get("tags");
|
|
// 返回前几个标签作为测试数据
|
return allTags != null ? allTags.stream().limit(2).toList() : Collections.emptyList();
|
}
|
|
return tags;
|
}
|
|
/**
|
* 步骤2: 上传头像图片(模拟前端上传logo.jpg)
|
*/
|
private String uploadAvatarImage() throws Exception {
|
String mutation = """
|
mutation {
|
saveMedia(
|
name: "logo.jpg"
|
path: "avatars/logo_test.jpg"
|
fileSize: 2048
|
fileExt: "jpg"
|
mediaType: 1
|
targetType: 1
|
targetId: 0
|
) {
|
id
|
name
|
path
|
}
|
}
|
""";
|
|
Map<String, String> request = Collections.singletonMap("query", mutation);
|
String response = postGraphQL(request);
|
|
Map<String, Object> responseMap = objectMapper.readValue(response, Map.class);
|
@SuppressWarnings("unchecked")
|
Map<String, Object> mediaData = (Map<String, Object>)
|
((Map<String, Object>) responseMap.get("data")).get("saveMedia");
|
|
Object idObj = mediaData.get("id");
|
return idObj != null ? idObj.toString() : null;
|
}
|
|
/**
|
* 步骤3: 创建评委(模拟前端提交表单)
|
*/
|
private String createJudgeWithAvatar(String mediaId, List<Map<String, Object>> availableTags) throws Exception {
|
// 选择前两个专业标签
|
List<String> selectedTagIds = availableTags.stream()
|
.limit(2)
|
.map(tag -> tag.get("id").toString())
|
.toList();
|
|
String tagIdsStr = "[" + String.join(", ", selectedTagIds) + "]";
|
|
String mutation = String.format("""
|
mutation {
|
saveJudge(input: {
|
name: "李四"
|
phone: "13700137000"
|
gender: 0
|
description: "资深技术专家,拥有丰富的项目经验和团队管理能力。"
|
specialtyIds: %s
|
avatarMediaId: %s
|
}) {
|
id
|
name
|
phone
|
gender
|
description
|
avatarUrl
|
specialties {
|
id
|
name
|
code
|
}
|
}
|
}
|
""", tagIdsStr, mediaId);
|
|
Map<String, String> request = Collections.singletonMap("query", mutation);
|
String response = postGraphQL(request);
|
|
Map<String, Object> responseMap = objectMapper.readValue(response, Map.class);
|
@SuppressWarnings("unchecked")
|
Map<String, Object> judgeData = (Map<String, Object>)
|
((Map<String, Object>) responseMap.get("data")).get("saveJudge");
|
|
Object idObj = judgeData.get("id");
|
return idObj != null ? idObj.toString() : null;
|
}
|
|
/**
|
* 步骤4: 验证数据库数据完整性
|
*/
|
private void verifyJudgeDataIntegrity(String judgeId, String mediaId) {
|
// 验证评委基本信息
|
String judgeSql = "SELECT * FROM t_judge WHERE id = ? AND state = 1";
|
Map<String, Object> judge = jdbcTemplate.queryForMap(judgeSql, Long.parseLong(judgeId));
|
|
assertEquals("李四", judge.get("name"));
|
assertEquals("13700137000", judge.get("phone"));
|
assertEquals(0, judge.get("gender")); // 女性
|
assertTrue(((String) judge.get("description")).contains("资深技术专家"));
|
|
// 验证媒体记录
|
String mediaSql = "SELECT * FROM t_media WHERE id = ? AND state = 1";
|
Map<String, Object> media = jdbcTemplate.queryForMap(mediaSql, Long.parseLong(mediaId));
|
|
assertEquals("logo.jpg", media.get("name"));
|
assertEquals(1, media.get("target_type")); // 评委头像
|
assertEquals(Long.parseLong(judgeId), ((Number) media.get("target_id")).longValue());
|
|
// 验证标签关联
|
String tagSql = "SELECT COUNT(*) FROM t_judge_tag WHERE judge_id = ? AND state = 1";
|
Integer tagCount = jdbcTemplate.queryForObject(tagSql, Integer.class, Long.parseLong(judgeId));
|
assertTrue(tagCount >= 2, "应该至少有2个标签关联");
|
|
System.out.println(" ✓ 评委基本信息正确");
|
System.out.println(" ✓ 头像媒体记录正确");
|
System.out.println(" ✓ 标签关联记录正确 (" + tagCount + "个)");
|
}
|
|
/**
|
* 步骤5: 查询评委详情(模拟前端查看详情)
|
*/
|
private Map<String, Object> getJudgeDetails(String judgeId) throws Exception {
|
String query = String.format("""
|
query {
|
judge(id: %s) {
|
id
|
name
|
phone
|
gender
|
description
|
avatarUrl
|
specialties {
|
id
|
name
|
code
|
}
|
}
|
}
|
""", judgeId);
|
|
Map<String, String> request = Collections.singletonMap("query", query);
|
String response = postGraphQL(request);
|
|
Map<String, Object> responseMap = objectMapper.readValue(response, Map.class);
|
@SuppressWarnings("unchecked")
|
Map<String, Object> judgeData = (Map<String, Object>)
|
((Map<String, Object>) responseMap.get("data")).get("judge");
|
|
return judgeData;
|
}
|
|
/**
|
* 打印测试总结
|
*/
|
private void printTestSummary(String judgeId, String mediaId, Map<String, Object> judgeDetails) {
|
System.out.println("\n=== 测试总结 ===");
|
System.out.println("评委ID: " + judgeId);
|
System.out.println("媒体ID: " + mediaId);
|
System.out.println("评委姓名: " + judgeDetails.get("name"));
|
System.out.println("联系电话: " + judgeDetails.get("phone"));
|
System.out.println("性别: " + (Integer.valueOf(0).equals(judgeDetails.get("gender")) ? "女" : "男"));
|
System.out.println("头像URL: " + judgeDetails.get("avatarUrl"));
|
|
@SuppressWarnings("unchecked")
|
List<Map<String, Object>> specialties = (List<Map<String, Object>>) judgeDetails.get("specialties");
|
System.out.println("专业标签数量: " + (specialties != null ? specialties.size() : 0));
|
if (specialties != null) {
|
for (Map<String, Object> specialty : specialties) {
|
System.out.println(" - " + specialty.get("name") + " (" + specialty.get("category") + ")");
|
}
|
}
|
|
System.out.println("\n✅ 所有测试步骤均成功完成!");
|
System.out.println("✅ 前端到后端的完整数据流程验证通过!");
|
System.out.println("✅ 数据库数据完整性验证通过!");
|
}
|
|
/**
|
* 发送GraphQL请求
|
*/
|
private String postGraphQL(Map<String, String> requestBody) {
|
HttpHeaders headers = new HttpHeaders();
|
headers.setContentType(MediaType.APPLICATION_JSON);
|
HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);
|
String url = "http://localhost:" + port + "/graphql";
|
|
var response = restTemplate.postForEntity(url, entity, String.class);
|
|
if (response.getStatusCode().is2xxSuccessful() && response.hasBody()) {
|
return response.getBody();
|
} else {
|
throw new RuntimeException("GraphQL request failed with status: " +
|
response.getStatusCode() + " and body: " + response.getBody());
|
}
|
}
|
}
|