Commit c00054eaf325c698ccf2e7342eced4ef0d0958a2
1 parent
57a1bbfc
test(usr): user list integration coverage REQ-USR-003
Showing
2 changed files
with
120 additions
and
0 deletions
backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java
| ... | ... | @@ -5,11 +5,13 @@ import com.xly.erp.module.usr.dto.CreateUserDTO; |
| 5 | 5 | import com.xly.erp.module.usr.dto.UpdateUserDTO; |
| 6 | 6 | import com.xly.erp.module.usr.service.UserService; |
| 7 | 7 | import jakarta.validation.Valid; |
| 8 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 8 | 9 | import org.springframework.web.bind.annotation.PathVariable; |
| 9 | 10 | import org.springframework.web.bind.annotation.PostMapping; |
| 10 | 11 | import org.springframework.web.bind.annotation.PutMapping; |
| 11 | 12 | import org.springframework.web.bind.annotation.RequestBody; |
| 12 | 13 | import org.springframework.web.bind.annotation.RequestMapping; |
| 14 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 13 | 15 | import org.springframework.web.bind.annotation.RestController; |
| 14 | 16 | |
| 15 | 17 | import java.util.Map; |
| ... | ... | @@ -35,4 +37,13 @@ public class UserController { |
| 35 | 37 | Integer updated = userService.update(id, dto); |
| 36 | 38 | return Result.ok(Map.of("iIncrement", updated)); |
| 37 | 39 | } |
| 40 | + | |
| 41 | + @GetMapping("/users") | |
| 42 | + public Result<Map<String, Object>> list(@RequestParam(required = false) String field, | |
| 43 | + @RequestParam(required = false) String match, | |
| 44 | + @RequestParam(required = false) String value, | |
| 45 | + @RequestParam(required = false) Integer pageNum, | |
| 46 | + @RequestParam(required = false) Integer pageSize) { | |
| 47 | + return Result.ok(userService.list(field, match, value, pageNum, pageSize)); | |
| 48 | + } | |
| 38 | 49 | } | ... | ... |
backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java
| ... | ... | @@ -370,6 +370,115 @@ class UserControllerIT { |
| 370 | 370 | assertThat(name).isEqualTo("原"); |
| 371 | 371 | } |
| 372 | 372 | |
| 373 | + @Test | |
| 374 | + void getDefaults_with_jwt_returns200_andList() throws Exception { | |
| 375 | + insertUserWithPerms("sp_test_lst_1", "查询1", null, null); | |
| 376 | + insertUserWithPerms("sp_test_lst_2", "查询2", null, null); | |
| 377 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 378 | + HttpHeaders headers = jsonHeaders(); | |
| 379 | + headers.set("Authorization", "Bearer " + token); | |
| 380 | + | |
| 381 | + ResponseEntity<String> resp = rest.exchange( | |
| 382 | + listUrl(""), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 383 | + | |
| 384 | + JsonNode jb = objectMapper.readTree(resp.getBody()); | |
| 385 | + assertThat(jb.get("code").asInt()).isZero(); | |
| 386 | + assertThat(jb.get("data").get("records").isArray()).isTrue(); | |
| 387 | + assertThat(jb.get("data").get("total").asInt()).isPositive(); | |
| 388 | + assertThat(jb.get("data").get("pageSize").asInt()).isEqualTo(20); | |
| 389 | + } | |
| 390 | + | |
| 391 | + @Test | |
| 392 | + void getKeywordContains_filtersByUsername() throws Exception { | |
| 393 | + insertUserWithPerms("sp_test_lst_kw1", "包含查询用户", null, null); | |
| 394 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 395 | + HttpHeaders headers = jsonHeaders(); | |
| 396 | + headers.set("Authorization", "Bearer " + token); | |
| 397 | + | |
| 398 | + ResponseEntity<String> resp = rest.exchange( | |
| 399 | + listUrl("?field=用户名&match=包含&value=包含查询"), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 400 | + | |
| 401 | + JsonNode data = objectMapper.readTree(resp.getBody()).get("data"); | |
| 402 | + for (JsonNode node : data.get("records")) { | |
| 403 | + assertThat(node.get("sUserName").asText()).contains("包含查询"); | |
| 404 | + } | |
| 405 | + } | |
| 406 | + | |
| 407 | + @Test | |
| 408 | + void getKeywordEquals_filtersExact() throws Exception { | |
| 409 | + insertUserWithPerms("sp_test_lst_eq", "等于精确", null, null); | |
| 410 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 411 | + HttpHeaders headers = jsonHeaders(); | |
| 412 | + headers.set("Authorization", "Bearer " + token); | |
| 413 | + | |
| 414 | + ResponseEntity<String> resp = rest.exchange( | |
| 415 | + listUrl("?field=用户号&match=等于&value=sp_test_lst_eq"), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 416 | + | |
| 417 | + JsonNode records = objectMapper.readTree(resp.getBody()).get("data").get("records"); | |
| 418 | + assertThat(records.size()).isEqualTo(1); | |
| 419 | + assertThat(records.get(0).get("sUserNo").asText()).isEqualTo("sp_test_lst_eq"); | |
| 420 | + } | |
| 421 | + | |
| 422 | + @Test | |
| 423 | + void getInvalidField_returns40001() throws Exception { | |
| 424 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 425 | + HttpHeaders headers = jsonHeaders(); | |
| 426 | + headers.set("Authorization", "Bearer " + token); | |
| 427 | + | |
| 428 | + ResponseEntity<String> resp = rest.exchange( | |
| 429 | + listUrl("?field=未知"), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 430 | + | |
| 431 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40001); | |
| 432 | + } | |
| 433 | + | |
| 434 | + @Test | |
| 435 | + void getPageSizeExceeds100_returns40002() throws Exception { | |
| 436 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 437 | + HttpHeaders headers = jsonHeaders(); | |
| 438 | + headers.set("Authorization", "Bearer " + token); | |
| 439 | + | |
| 440 | + ResponseEntity<String> resp = rest.exchange( | |
| 441 | + listUrl("?pageSize=200"), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 442 | + | |
| 443 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40002); | |
| 444 | + } | |
| 445 | + | |
| 446 | + @Test | |
| 447 | + void getNoMatch_returnsEmptyArray() throws Exception { | |
| 448 | + String token = testJwtHelper.signFor("ADMIN001"); | |
| 449 | + HttpHeaders headers = jsonHeaders(); | |
| 450 | + headers.set("Authorization", "Bearer " + token); | |
| 451 | + | |
| 452 | + ResponseEntity<String> resp = rest.exchange( | |
| 453 | + listUrl("?field=用户号&match=等于&value=不存在的用户号XYZ"), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 454 | + | |
| 455 | + JsonNode data = objectMapper.readTree(resp.getBody()).get("data"); | |
| 456 | + assertThat(data.get("records").isArray()).isTrue(); | |
| 457 | + assertThat(data.get("records").size()).isZero(); | |
| 458 | + assertThat(data.get("total").asInt()).isZero(); | |
| 459 | + } | |
| 460 | + | |
| 461 | + @Test | |
| 462 | + void getWithoutJwt_permitAllStub_returns200() throws Exception { | |
| 463 | + HttpHeaders headers = jsonHeaders(); | |
| 464 | + ResponseEntity<String> resp = rest.exchange( | |
| 465 | + listUrl(""), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 466 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isZero(); | |
| 467 | + } | |
| 468 | + | |
| 469 | + @Test | |
| 470 | + void getTamperedJwt_returns20001() throws Exception { | |
| 471 | + HttpHeaders headers = jsonHeaders(); | |
| 472 | + headers.set("Authorization", "Bearer not.a.real.jwt"); | |
| 473 | + ResponseEntity<String> resp = rest.exchange( | |
| 474 | + listUrl(""), HttpMethod.GET, new HttpEntity<>(headers), String.class); | |
| 475 | + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001); | |
| 476 | + } | |
| 477 | + | |
| 478 | + private String listUrl(String querySuffix) { | |
| 479 | + return "http://localhost:" + port + "/api/usr/users" + querySuffix; | |
| 480 | + } | |
| 481 | + | |
| 373 | 482 | private String idUrl(Integer id) { |
| 374 | 483 | return "http://localhost:" + port + "/api/usr/users/" + id; |
| 375 | 484 | } | ... | ... |