Spring Boot本地测试@PutMapping接口update方法数据传输问题
问题梳理
- 远程PostgreSQL数据库权限报错:
org.postgresql.util.PSQLException: ERROR: permission denied for table TEST_Company
- 业务问题:更新操作中仅
SstRegistrationNo字段未同步到数据库,怀疑与toCompanyResponse方法有关,但不确定 - 需求:本地测试数据传输的方法,以及单元测试实现方案
一、先解决远程数据库权限问题
这是接口测试的前提,需给数据库用户授予TEST_Company表的更新权限,执行PostgreSQL命令:
-- 授予更新权限 GRANT UPDATE ON TEST_Company TO 你的数据库用户名; -- 若需要全表操作权限,可执行 GRANT ALL PRIVILEGES ON TEST_Company TO 你的数据库用户名;
二、排查SstRegistrationNo字段未同步问题
注意:toCompanyResponse仅负责将实体转为响应DTO,不影响数据库写入逻辑,数据库写入是在repository.save(companyEntityToBeUpdated)步骤完成的,建议从以下方向排查:
- 检查
Company类的sstRegistrationNo字段:是否有正确的JSON序列化/反序列化注解(如@JsonProperty),确保Postman传入的JSON字段名与实体类字段匹配(注意大小写、下划线命名差异) - 检查
CompanyEntity类的sstRegistrationNo字段:是否通过@Column注解正确映射到数据库列(例如数据库列是sst_registration_no,实体类需对应配置) - 验证传入数据:在
update方法中添加日志,打印company.getSstRegistrationNo()的值,确认请求是否正确传递了该字段
三、本地测试数据传输的方法
1. 使用H2内存数据库本地验证
添加H2依赖(pom.xml):
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>
配置application-test.yml:
spring: datasource: url: jdbc:h2:mem:testdb driverClassName: org.h2.Driver username: sa password: jpa: hibernate: ddl-auto: create-drop show-sql: true h2: console: enabled: true
启动项目后,访问http://localhost:8080/h2-console即可查看内存数据库,测试接口时可直接验证数据是否正确写入。
2. 打印SQL语句验证执行逻辑
在application.yml中开启SQL日志,查看实际执行的UPDATE语句是否包含SstRegistrationNo字段:
spring: jpa: show-sql: true properties: hibernate: format_sql: true
控制台会输出格式化后的SQL语句,可直接确认更新字段是否完整。
3. 本地断点调试
在repository.save()方法前添加断点,查看companyEntityToBeUpdated对象的sstRegistrationNo字段值,确认业务逻辑是否正确设置了该字段。
四、单元测试方案
1. 服务层单元测试(Mock Repository)
用Mockito模拟Repository,验证update方法的字段赋值逻辑:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class CompanyServiceTest { @Mock private CompanyRepository repository; @Mock private SeedValueRepository seedValueRepository; @InjectMocks private CompanyService companyService; @Test void update_ShouldUpdateSstRegistrationNo() { // 测试数据准备 Long companyId = 1L; Company request = new Company(); request.setSstRegistrationNo("SST-2024-001"); CompanyEntity existingEntity = new CompanyEntity(); existingEntity.setId(companyId); existingEntity.setSstRegistrationNo("OLD-SST-001"); // Mock Repository行为 when(repository.findById(companyId)).thenReturn(java.util.Optional.of(existingEntity)); when(repository.save(any(CompanyEntity.class))).thenReturn(existingEntity); // 执行测试方法 companyService.update(companyId, request); // 验证字段更新 assertEquals("SST-2024-001", existingEntity.getSstRegistrationNo()); // 验证save方法被调用 verify(repository, times(1)).save(existingEntity); } }
2. 控制器层集成测试
用MockMvc测试接口请求的参数传递:
import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(CompanyController.class) class CompanyControllerTest { @Autowired private MockMvc mockMvc; @MockBean private CompanyService companyService; @Test void update_ShouldPassSstRegistrationNo() throws Exception { Long companyId = 1L; String requestJson = "{\"sstRegistrationNo\":\"SST-2024-001\"}"; when(companyService.update(eq(companyId), any(Company.class))).thenReturn(new CompanyResponse()); mockMvc.perform(put("/companies/{companyId}", companyId) .contentType(MediaType.APPLICATION_JSON) .content(requestJson)) .andExpect(status().isOk()); verify(companyService, times(1)).update(eq(companyId), any(Company.class)); } }
内容的提问来源于stack exchange,提问作者Irfan
相关产品推荐
相关产品推荐

