From ac7704a5c1bfdcc95933bd8286515a252f144f6d Mon Sep 17 00:00:00 2001 From: zichun Date: Thu, 30 Apr 2026 14:30:04 +0800 Subject: [PATCH] test(usr): user update integration coverage REQ-USR-002 --- backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java | 10 ++++++++++ backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java | 195 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+), 0 deletions(-) diff --git a/backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java b/backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java index 1a81a76..2b03087 100644 --- a/backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java +++ b/backend/src/main/java/com/xly/erp/module/usr/controller/UserController.java @@ -2,9 +2,12 @@ package com.xly.erp.module.usr.controller; import com.xly.erp.common.response.Result; import com.xly.erp.module.usr.dto.CreateUserDTO; +import com.xly.erp.module.usr.dto.UpdateUserDTO; import com.xly.erp.module.usr.service.UserService; import jakarta.validation.Valid; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -25,4 +28,11 @@ public class UserController { public Result> create(@Valid @RequestBody CreateUserDTO dto) { return Result.ok(userService.create(dto)); } + + @PutMapping("/users/{id}") + public Result> update(@PathVariable Integer id, + @Valid @RequestBody UpdateUserDTO dto) { + Integer updated = userService.update(id, dto); + return Result.ok(Map.of("iIncrement", updated)); + } } diff --git a/backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java b/backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java index 8db04a2..41596b8 100644 --- a/backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java +++ b/backend/src/test/java/com/xly/erp/module/usr/controller/UserControllerIT.java @@ -197,6 +197,201 @@ class UserControllerIT { assertThat(count).isZero(); } + @Test + void putValidBody_with_jwt_returns200_andUpdates() throws Exception { + Integer staffId = insertStaff("sp_test_pst1", "员工1"); + Integer cat1 = insertCategory("sp_test_pc_p1", "权限1"); + Integer cat2 = insertCategory("sp_test_pc_p2", "权限2"); + Integer userId = insertUserWithPerms("sp_test_u_putorig", "原用户", staffId, cat1); + + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_putorig", "原用户改名"); + body.put("permissionCategoryIds", List.of(cat1, cat2)); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + JsonNode jb = objectMapper.readTree(resp.getBody()); + assertThat(jb.get("code").asInt()).isZero(); + assertThat(jb.get("data").get("iIncrement").asInt()).isEqualTo(userId); + + Map row = jdbcTemplate.queryForMap( + "SELECT sUserName, sPasswordHash, sCreatedBy FROM tUser WHERE iIncrement = ?", userId); + assertThat(row.get("sUserName")).isEqualTo("原用户改名"); + assertThat((String) row.get("sPasswordHash")).startsWith("$2a$"); + assertThat(row.get("sCreatedBy")).isEqualTo("ORIG_CREATOR"); + + Integer permCount = jdbcTemplate.queryForObject( + "SELECT COUNT(1) FROM tUserPermission WHERE iUserId = ?", Integer.class, userId); + assertThat(permCount).isEqualTo(2); + } + + @Test + void putNonExistentId_returns40400() throws Exception { + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_no", "无"); + + ResponseEntity resp = rest.exchange( + idUrl(99999990), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40400); + } + + @Test + void putAlreadyDeletedId_returns40400() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_deleted", "已删", null, null); + jdbcTemplate.update("UPDATE tUser SET bDeleted = 1 WHERE iIncrement = ?", userId); + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(baseBody("sp_test_u_deleted", "改"), headers), + String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40400); + } + + @Test + void putInvalidUserType_returns40001() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_pinvtype", "原", null, null); + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_pinvtype", "改"); + body.put("sUserType", "火星"); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40001); + } + + @Test + void putDuplicateUserNo_returns40020() throws Exception { + Integer u1 = insertUserWithPerms("sp_test_u_pdupA", "AAA", null, null); + Integer u2 = insertUserWithPerms("sp_test_u_pdupB", "BBB", null, null); + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_pdupA", "改成 A"); + + ResponseEntity resp = rest.exchange( + idUrl(u2), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40020); + } + + @Test + void putStaffNotFound_returns40022() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_pstaff", "原", null, null); + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_pstaff", "改"); + body.put("iStaffId", 99999990); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40022); + } + + @Test + void putPermissionCategoryNotFound_returns40023() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_pperm", "原", null, null); + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_pperm", "改"); + body.put("permissionCategoryIds", List.of(99999991)); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(40023); + } + + @Test + void putWithEmptyPermissionIds_clearsAssociations() throws Exception { + Integer cat1 = insertCategory("sp_test_pc_e1", "权限"); + Integer userId = insertUserWithPerms("sp_test_u_pclear", "原", null, cat1); + + String token = testJwtHelper.signFor("ADMIN001"); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer " + token); + Map body = baseBody("sp_test_u_pclear", "改"); + body.remove("permissionCategoryIds"); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isZero(); + Integer permCount = jdbcTemplate.queryForObject( + "SELECT COUNT(1) FROM tUserPermission WHERE iUserId = ?", Integer.class, userId); + assertThat(permCount).isZero(); + String passHash = jdbcTemplate.queryForObject( + "SELECT sPasswordHash FROM tUser WHERE iIncrement = ?", String.class, userId); + assertThat(passHash).startsWith("$2a$"); + } + + @Test + void putWithoutJwt_permitAllStub_returns200_andDoesNotChangeCreatedBy() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_pnojwt", "原", null, null); + HttpHeaders headers = jsonHeaders(); + Map body = baseBody("sp_test_u_pnojwt", "改"); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isZero(); + String createdBy = jdbcTemplate.queryForObject( + "SELECT sCreatedBy FROM tUser WHERE iIncrement = ?", String.class, userId); + assertThat(createdBy).isEqualTo("ORIG_CREATOR"); + } + + @Test + void putTamperedJwt_returns20001() throws Exception { + Integer userId = insertUserWithPerms("sp_test_u_ptamper", "原", null, null); + HttpHeaders headers = jsonHeaders(); + headers.set("Authorization", "Bearer not.a.real.jwt"); + Map body = baseBody("sp_test_u_ptamper", "改"); + + ResponseEntity resp = rest.exchange( + idUrl(userId), HttpMethod.PUT, new HttpEntity<>(body, headers), String.class); + + assertThat(objectMapper.readTree(resp.getBody()).get("code").asInt()).isEqualTo(20001); + String name = jdbcTemplate.queryForObject( + "SELECT sUserName FROM tUser WHERE iIncrement = ?", String.class, userId); + assertThat(name).isEqualTo("原"); + } + + private String idUrl(Integer id) { + return "http://localhost:" + port + "/api/usr/users/" + id; + } + + private Integer insertUserWithPerms(String userNo, String userName, Integer staffId, Integer catId) { + jdbcTemplate.update( + "INSERT INTO tUser (sBrandsId, sSubsidiaryId, tCreateDate, sUserNo, sUserName, iStaffId, " + + "sUserType, sLanguage, bCanModifyDocs, sPasswordHash, sCreatedBy, bDeleted) " + + "VALUES ('XLY','XLY', NOW(), ?, ?, ?, '普通用户', 'zh', 0, " + + "'$2a$10$origHashOrigHashOrigHashOrigHashOrigHashOrigHashOrig', 'ORIG_CREATOR', 0)", + userNo, userName, staffId); + Integer userId = jdbcTemplate.queryForObject( + "SELECT iIncrement FROM tUser WHERE sUserNo = ?", Integer.class, userNo); + if (catId != null) { + jdbcTemplate.update( + "INSERT INTO tUserPermission (sBrandsId, sSubsidiaryId, tCreateDate, iUserId, iCategoryId, sCreatedBy) " + + "VALUES ('XLY','XLY', NOW(), ?, ?, 'ORIG_CREATOR')", + userId, catId); + } + return userId; + } + private Integer insertStaff(String staffNo, String name) { jdbcTemplate.update( "INSERT INTO tStaff (sBrandsId, sSubsidiaryId, tCreateDate, sStaffNo, sStaffName, sCreatedBy, bDeleted) " -- libgit2 0.22.2