暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

my_dic_table_batch_test.go 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "io"
  6. "net/http"
  7. "testing"
  8. "git.x2erp.com/qdy/go-svc-configure/internal/service/dicmanagement"
  9. )
  10. const (
  11. batchTestBaseURL = "http://localhost:8080"
  12. batchTestTable1 = "batch_test_table_001"
  13. batchTestTable2 = "batch_test_table_002"
  14. batchTestTable3 = "batch_test_table_003"
  15. )
  16. // getAuthToken 获取认证token
  17. func getAuthToken(t *testing.T) string {
  18. // 使用同一包中已存在的函数
  19. userToken, err := getUserAuthToken(t)
  20. if err != nil {
  21. t.Fatalf("获取用户认证token失败: %v", err)
  22. }
  23. configToken, err := createConfigToken(t, userToken)
  24. if err != nil {
  25. t.Fatalf("创建配置token失败: %v", err)
  26. }
  27. return configToken
  28. }
  29. // getUserAuthToken 获取用户认证token
  30. // TestBatchSaveDicTables 测试批量保存数据库表字典
  31. func TestBatchSaveDicTables(t *testing.T) {
  32. // 1. 批量创建多个表
  33. t.Run("BatchCreateTables", testBatchCreateTables)
  34. // 2. 验证批量创建的表
  35. t.Run("VerifyBatchCreatedTables", testVerifyBatchCreatedTables)
  36. // 3. 批量更新表(部分表更新,部分表新增)
  37. t.Run("BatchUpdateTables", testBatchUpdateTables)
  38. // 4. 验证批量更新结果
  39. t.Run("VerifyBatchUpdateResults", testVerifyBatchUpdateResults)
  40. // 5. 清理测试数据
  41. t.Run("CleanupBatchTestData", testCleanupBatchTestData)
  42. }
  43. func testBatchCreateTables(t *testing.T) {
  44. httpClient := &http.Client{}
  45. token := getAuthToken(t)
  46. url := batchTestBaseURL + "/api/dic-table/batch-save"
  47. // 创建批量保存请求
  48. reqBody := dicmanagement.BatchSaveDicTablesRequest{
  49. Tables: []dicmanagement.DicTableRequest{
  50. {
  51. TableID: batchTestTable1,
  52. TableType: "实体表",
  53. Name: "批量测试表001",
  54. Description: "批量测试表001描述",
  55. },
  56. {
  57. TableID: batchTestTable2,
  58. TableType: "视图",
  59. Name: "批量测试表002",
  60. Description: "批量测试表002描述",
  61. },
  62. },
  63. Fields: []dicmanagement.DicTableFieldRequest{
  64. // 表1的字段
  65. {
  66. FieldID: batchTestTable1 + ".id",
  67. TableID: batchTestTable1,
  68. FiledType: "实际字段",
  69. DataType: "数值型",
  70. FieldName: "id",
  71. FieldNameCN: "主键ID",
  72. Description: "表1主键字段",
  73. },
  74. {
  75. FieldID: batchTestTable1 + ".name",
  76. TableID: batchTestTable1,
  77. FiledType: "实际字段",
  78. DataType: "字符型",
  79. FieldName: "name",
  80. FieldNameCN: "名称",
  81. Description: "表1名称字段",
  82. },
  83. // 表2的字段
  84. {
  85. FieldID: batchTestTable2 + ".code",
  86. TableID: batchTestTable2,
  87. FiledType: "实际字段",
  88. DataType: "字符型",
  89. FieldName: "code",
  90. FieldNameCN: "编码",
  91. Description: "表2编码字段",
  92. },
  93. {
  94. FieldID: batchTestTable2 + ".value",
  95. TableID: batchTestTable2,
  96. FiledType: "计算字段",
  97. DataType: "数值型",
  98. FieldName: "value",
  99. FieldNameCN: "数值",
  100. Description: "表2数值字段",
  101. },
  102. },
  103. }
  104. jsonData, err := json.Marshal(reqBody)
  105. if err != nil {
  106. t.Fatalf("JSON序列化失败: %v", err)
  107. }
  108. req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
  109. if err != nil {
  110. t.Fatalf("创建请求失败: %v", err)
  111. }
  112. // 使用Bearer Token认证
  113. req.Header.Set("Authorization", "Bearer "+token)
  114. req.Header.Set("Content-Type", "application/json")
  115. resp, err := httpClient.Do(req)
  116. if err != nil {
  117. t.Fatalf("请求失败: %v", err)
  118. }
  119. defer resp.Body.Close()
  120. body, err := io.ReadAll(resp.Body)
  121. if err != nil {
  122. t.Fatalf("读取响应失败: %v", err)
  123. }
  124. var result map[string]interface{}
  125. if err := json.Unmarshal(body, &result); err != nil {
  126. t.Fatalf("JSON解析失败: %v", err)
  127. }
  128. if success, ok := result["success"].(bool); !ok || !success {
  129. t.Errorf("批量创建表失败: %v", result)
  130. } else {
  131. t.Logf("批量创建表成功: %s", string(body))
  132. }
  133. }
  134. func testVerifyBatchCreatedTables(t *testing.T) {
  135. httpClient := &http.Client{}
  136. // 验证表1
  137. verifyTable(t, httpClient, batchTestTable1, "实体表", "批量测试表001", "批量测试表001描述", 2)
  138. // 验证表2
  139. verifyTable(t, httpClient, batchTestTable2, "视图", "批量测试表002", "批量测试表002描述", 2)
  140. }
  141. func verifyTable(t *testing.T, client *http.Client, tableID, expectedType, expectedName, expectedDesc string, expectedFieldCount int) {
  142. token := getAuthToken(t)
  143. url := batchTestBaseURL + "/api/dic-table/detail/" + tableID
  144. req, err := http.NewRequest("POST", url, nil)
  145. if err != nil {
  146. t.Errorf("创建请求失败: %v", err)
  147. return
  148. }
  149. req.Header.Set("Authorization", "Bearer "+token)
  150. req.Header.Set("Content-Type", "application/json")
  151. resp, err := client.Do(req)
  152. if err != nil {
  153. t.Errorf("请求失败: %v", err)
  154. return
  155. }
  156. defer resp.Body.Close()
  157. body, err := io.ReadAll(resp.Body)
  158. if err != nil {
  159. t.Errorf("读取响应失败: %v", err)
  160. return
  161. }
  162. var result map[string]interface{}
  163. if err := json.Unmarshal(body, &result); err != nil {
  164. t.Errorf("JSON解析失败: %v", err)
  165. return
  166. }
  167. if success, ok := result["success"].(bool); !ok || !success {
  168. t.Errorf("查询表 %s 详情失败: %v", tableID, result)
  169. return
  170. }
  171. // 验证表信息
  172. if data, ok := result["data"].(map[string]interface{}); ok {
  173. if tableData, ok := data["table"].(map[string]interface{}); ok {
  174. if actualID, ok := tableData["tableID"].(string); !ok || actualID != tableID {
  175. t.Errorf("表ID不匹配: 期望 %s, 实际 %v", tableID, tableData["tableID"])
  176. }
  177. if actualType, ok := tableData["tableType"].(string); !ok || actualType != expectedType {
  178. t.Errorf("表类型不匹配: 期望 %s, 实际 %v", expectedType, tableData["tableType"])
  179. }
  180. if actualName, ok := tableData["name"].(string); !ok || actualName != expectedName {
  181. t.Errorf("表名称不匹配: 期望 %s, 实际 %v", expectedName, tableData["name"])
  182. }
  183. if actualDesc, ok := tableData["description"].(string); !ok || actualDesc != expectedDesc {
  184. t.Errorf("表描述不匹配: 期望 %s, 实际 %v", expectedDesc, tableData["description"])
  185. }
  186. }
  187. // 验证字段数量
  188. if fields, ok := data["fields"].([]interface{}); ok {
  189. if len(fields) != expectedFieldCount {
  190. t.Errorf("表 %s 字段数量不匹配: 期望 %d, 实际 %d", tableID, expectedFieldCount, len(fields))
  191. }
  192. } else {
  193. t.Errorf("表 %s 字段列表不存在", tableID)
  194. }
  195. }
  196. }
  197. func testBatchUpdateTables(t *testing.T) {
  198. httpClient := &http.Client{}
  199. token := getAuthToken(t)
  200. url := batchTestBaseURL + "/api/dic-table/batch-save"
  201. // 更新请求:更新表1,新增表3,表2保持不变(不在请求中)
  202. reqBody := dicmanagement.BatchSaveDicTablesRequest{
  203. Tables: []dicmanagement.DicTableRequest{
  204. {
  205. TableID: batchTestTable1,
  206. TableType: "实体表",
  207. Name: "更新后的批量测试表001",
  208. Description: "更新后的批量测试表001描述",
  209. },
  210. {
  211. TableID: batchTestTable3,
  212. TableType: "物化视图",
  213. Name: "批量测试表003",
  214. Description: "批量测试表003描述",
  215. },
  216. },
  217. Fields: []dicmanagement.DicTableFieldRequest{
  218. // 更新表1的字段(新增一个字段,修改一个字段)
  219. {
  220. FieldID: batchTestTable1 + ".id",
  221. TableID: batchTestTable1,
  222. FiledType: "实际字段",
  223. DataType: "数值型",
  224. FieldName: "id",
  225. FieldNameCN: "更新后的主键ID",
  226. Description: "表1更新后的主键字段",
  227. },
  228. {
  229. FieldID: batchTestTable1 + ".status",
  230. TableID: batchTestTable1,
  231. FiledType: "实际字段",
  232. DataType: "字符型",
  233. FieldName: "status",
  234. FieldNameCN: "状态",
  235. Description: "表1新增的状态字段",
  236. },
  237. // 表3的字段
  238. {
  239. FieldID: batchTestTable3 + ".id",
  240. TableID: batchTestTable3,
  241. FiledType: "实际字段",
  242. DataType: "数值型",
  243. FieldName: "id",
  244. FieldNameCN: "主键ID",
  245. Description: "表3主键字段",
  246. },
  247. },
  248. }
  249. jsonData, err := json.Marshal(reqBody)
  250. if err != nil {
  251. t.Fatalf("JSON序列化失败: %v", err)
  252. }
  253. req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
  254. if err != nil {
  255. t.Fatalf("创建请求失败: %v", err)
  256. }
  257. req.Header.Set("Authorization", "Bearer "+token)
  258. req.Header.Set("Content-Type", "application/json")
  259. resp, err := httpClient.Do(req)
  260. if err != nil {
  261. t.Fatalf("请求失败: %v", err)
  262. }
  263. defer resp.Body.Close()
  264. body, err := io.ReadAll(resp.Body)
  265. if err != nil {
  266. t.Fatalf("读取响应失败: %v", err)
  267. }
  268. var result map[string]interface{}
  269. if err := json.Unmarshal(body, &result); err != nil {
  270. t.Fatalf("JSON解析失败: %v", err)
  271. }
  272. if success, ok := result["success"].(bool); !ok || !success {
  273. t.Errorf("批量更新表失败: %v", result)
  274. } else {
  275. t.Logf("批量更新表成功: %s", string(body))
  276. }
  277. }
  278. func testVerifyBatchUpdateResults(t *testing.T) {
  279. httpClient := &http.Client{}
  280. // 验证表1已更新
  281. verifyTable(t, httpClient, batchTestTable1, "实体表", "更新后的批量测试表001", "更新后的批量测试表001描述", 2)
  282. // 验证表2保持不变(不在批量更新请求中,应该保持原样)
  283. verifyTable(t, httpClient, batchTestTable2, "视图", "批量测试表002", "批量测试表002描述", 2)
  284. // 验证表3已创建
  285. verifyTable(t, httpClient, batchTestTable3, "物化视图", "批量测试表003", "批量测试表003描述", 1)
  286. // 详细验证表1的字段更新
  287. verifyTableFields(t, httpClient, batchTestTable1)
  288. }
  289. func verifyTableFields(t *testing.T, client *http.Client, tableID string) {
  290. token := getAuthToken(t)
  291. url := batchTestBaseURL + "/api/dic-table/detail/" + tableID
  292. req, err := http.NewRequest("POST", url, nil)
  293. if err != nil {
  294. t.Errorf("创建请求失败: %v", err)
  295. return
  296. }
  297. req.Header.Set("Authorization", "Bearer "+token)
  298. req.Header.Set("Content-Type", "application/json")
  299. resp, err := client.Do(req)
  300. if err != nil {
  301. t.Errorf("请求失败: %v", err)
  302. return
  303. }
  304. defer resp.Body.Close()
  305. body, err := io.ReadAll(resp.Body)
  306. if err != nil {
  307. t.Errorf("读取响应失败: %v", err)
  308. return
  309. }
  310. var result map[string]interface{}
  311. if err := json.Unmarshal(body, &result); err != nil {
  312. t.Errorf("JSON解析失败: %v", err)
  313. return
  314. }
  315. if success, ok := result["success"].(bool); !ok || !success {
  316. t.Errorf("查询表 %s 详情失败: %v", tableID, result)
  317. return
  318. }
  319. if data, ok := result["data"].(map[string]interface{}); ok {
  320. if fields, ok := data["fields"].([]interface{}); ok {
  321. // 检查特定字段是否存在
  322. idFieldFound := false
  323. statusFieldFound := false
  324. nameFieldFound := false
  325. for _, field := range fields {
  326. fieldMap := field.(map[string]interface{})
  327. if fieldName, ok := fieldMap["fieldName"].(string); ok {
  328. switch fieldName {
  329. case "id":
  330. idFieldFound = true
  331. if fieldNameCN, ok := fieldMap["fieldNameCN"].(string); !ok || fieldNameCN != "更新后的主键ID" {
  332. t.Errorf("表 %s id字段中文名称未更新", tableID)
  333. }
  334. case "status":
  335. statusFieldFound = true
  336. case "name":
  337. nameFieldFound = true
  338. }
  339. }
  340. }
  341. if tableID == batchTestTable1 {
  342. if !idFieldFound {
  343. t.Errorf("表 %s 缺少id字段", tableID)
  344. }
  345. if !statusFieldFound {
  346. t.Errorf("表 %s 缺少status字段", tableID)
  347. }
  348. if nameFieldFound {
  349. t.Errorf("表 %s 不应该有name字段(应该被删除)", tableID)
  350. }
  351. }
  352. }
  353. }
  354. }
  355. func testCleanupBatchTestData(t *testing.T) {
  356. httpClient := &http.Client{}
  357. // 删除测试表
  358. tables := []string{batchTestTable1, batchTestTable2, batchTestTable3}
  359. for _, tableID := range tables {
  360. deleteTable(t, httpClient, tableID)
  361. }
  362. }
  363. func deleteTable(t *testing.T, client *http.Client, tableID string) {
  364. token := getAuthToken(t)
  365. url := batchTestBaseURL + "/api/dic-table/delete/" + tableID
  366. req, err := http.NewRequest("POST", url, nil)
  367. if err != nil {
  368. t.Errorf("创建删除请求失败: %v", err)
  369. return
  370. }
  371. req.Header.Set("Authorization", "Bearer "+token)
  372. req.Header.Set("Content-Type", "application/json")
  373. resp, err := client.Do(req)
  374. if err != nil {
  375. t.Errorf("删除请求失败: %v", err)
  376. return
  377. }
  378. defer resp.Body.Close()
  379. body, err := io.ReadAll(resp.Body)
  380. if err != nil {
  381. t.Errorf("读取响应失败: %v", err)
  382. return
  383. }
  384. var result map[string]interface{}
  385. if err := json.Unmarshal(body, &result); err != nil {
  386. t.Errorf("JSON解析失败: %v", err)
  387. return
  388. }
  389. if success, ok := result["success"].(bool); !ok || !success {
  390. t.Errorf("删除表 %s 失败: %v", tableID, result)
  391. } else {
  392. t.Logf("删除表 %s 成功", tableID)
  393. }
  394. }
  395. // TestBatchSaveValidation 测试批量保存的验证逻辑
  396. func TestBatchSaveValidation(t *testing.T) {
  397. httpClient := &http.Client{}
  398. url := batchTestBaseURL + "/api/dic-table/batch-save"
  399. testCases := []struct {
  400. name string
  401. reqBody dicmanagement.BatchSaveDicTablesRequest
  402. expectError bool
  403. }{
  404. {
  405. name: "空表集合",
  406. reqBody: dicmanagement.BatchSaveDicTablesRequest{
  407. Tables: []dicmanagement.DicTableRequest{},
  408. Fields: []dicmanagement.DicTableFieldRequest{
  409. {
  410. FieldID: "test.id",
  411. TableID: "test",
  412. FiledType: "实际字段",
  413. DataType: "数值型",
  414. FieldName: "id",
  415. FieldNameCN: "主键",
  416. },
  417. },
  418. },
  419. expectError: true,
  420. },
  421. {
  422. name: "空字段集合",
  423. reqBody: dicmanagement.BatchSaveDicTablesRequest{
  424. Tables: []dicmanagement.DicTableRequest{
  425. {
  426. TableID: "test",
  427. TableType: "实体表",
  428. Name: "测试表",
  429. },
  430. },
  431. Fields: []dicmanagement.DicTableFieldRequest{},
  432. },
  433. expectError: true,
  434. },
  435. {
  436. name: "字段引用不存在的表",
  437. reqBody: dicmanagement.BatchSaveDicTablesRequest{
  438. Tables: []dicmanagement.DicTableRequest{
  439. {
  440. TableID: "table1",
  441. TableType: "实体表",
  442. Name: "表1",
  443. },
  444. },
  445. Fields: []dicmanagement.DicTableFieldRequest{
  446. {
  447. FieldID: "table2.id",
  448. TableID: "table2", // 这个表不在Tables中
  449. FiledType: "实际字段",
  450. DataType: "数值型",
  451. FieldName: "id",
  452. FieldNameCN: "主键",
  453. },
  454. },
  455. },
  456. expectError: true,
  457. },
  458. {
  459. name: "字段ID格式错误",
  460. reqBody: dicmanagement.BatchSaveDicTablesRequest{
  461. Tables: []dicmanagement.DicTableRequest{
  462. {
  463. TableID: "test",
  464. TableType: "实体表",
  465. Name: "测试表",
  466. },
  467. },
  468. Fields: []dicmanagement.DicTableFieldRequest{
  469. {
  470. FieldID: "wrong_format", // 应该为 test.id
  471. TableID: "test",
  472. FiledType: "实际字段",
  473. DataType: "数值型",
  474. FieldName: "id",
  475. FieldNameCN: "主键",
  476. },
  477. },
  478. },
  479. expectError: true,
  480. },
  481. }
  482. for _, tc := range testCases {
  483. t.Run(tc.name, func(t *testing.T) {
  484. token := getAuthToken(t)
  485. jsonData, err := json.Marshal(tc.reqBody)
  486. if err != nil {
  487. t.Fatalf("JSON序列化失败: %v", err)
  488. }
  489. req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
  490. if err != nil {
  491. t.Fatalf("创建请求失败: %v", err)
  492. }
  493. req.Header.Set("Authorization", "Bearer "+token)
  494. req.Header.Set("Content-Type", "application/json")
  495. resp, err := httpClient.Do(req)
  496. if err != nil {
  497. t.Fatalf("请求失败: %v", err)
  498. }
  499. defer resp.Body.Close()
  500. body, err := io.ReadAll(resp.Body)
  501. if err != nil {
  502. t.Fatalf("读取响应失败: %v", err)
  503. }
  504. var result map[string]interface{}
  505. if err := json.Unmarshal(body, &result); err != nil {
  506. t.Fatalf("JSON解析失败: %v", err)
  507. }
  508. success, ok := result["success"].(bool)
  509. if !ok {
  510. t.Errorf("响应格式错误: %v", result)
  511. return
  512. }
  513. if tc.expectError && success {
  514. t.Errorf("期望验证失败但请求成功: %v", result)
  515. } else if !tc.expectError && !success {
  516. t.Errorf("期望请求成功但验证失败: %v", result)
  517. } else {
  518. t.Logf("验证测试通过: %s", tc.name)
  519. }
  520. })
  521. }
  522. }