Spring REST分页结果控制器测试报错问题求助
解决方案:MockMvc测试Page接口JSON解析错误问题
问题根源
你遇到的IllegalStateException: org.json.JSONException: Unparsable JSON string错误,本质是org.json库无法解析Spring Data Page类型序列化后的复杂JSON结构(Page包含content、pageable、sort等嵌套对象),而改用List时结构简单,所以解析正常。要验证分页信息,需换用Spring原生的Jackson工具或JsonPath来处理。
具体解决步骤
1. 确保MockMvc配置正确的Jackson消息转换器
Spring Data的Page类型需要PageJacksonModule支持序列化/反序列化,测试时要确保MockMvc使用配置了该模块的ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.data.web.PageJacksonModule; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; @Autowired private YourUserController userController; @Autowired private ObjectMapper objectMapper; @BeforeEach void setUp() { // 注册Page序列化模块 objectMapper.registerModule(new PageJacksonModule()); // 配置MockMvc使用Jackson消息转换器 mockMvc = MockMvcBuilders.standaloneSetup(userController) .setMessageConverters(new MappingJackson2HttpMessageConverter(objectMapper)) .build(); }
如果使用@WebMvcTest注解,Spring会自动配置兼容的ObjectMapper,只需确保依赖中包含spring-data-commons(PageJacksonModule在该包内)。
2. 用JsonPath直接验证分页信息
无需手动解析JSON字符串,直接用MockMvc的jsonPath断言分页相关字段,简洁高效:
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @Test void testUserPagination() throws Exception { mockMvc.perform(get("/users") .param("page", "0") .param("size", "10") .param("sort", "id,asc")) // 验证响应状态 .andExpect(status().isOk()) // 验证内容数量 .andExpect(jsonPath("$.content.length()").value(10)) // 验证总元素数 .andExpect(jsonPath("$.totalElements").value(100)) // 验证每页大小 .andExpect(jsonPath("$.pageable.pageSize").value(10)) // 验证排序状态和字段 .andExpect(jsonPath("$.sort.sorted").value(true)) .andExpect(jsonPath("$.sort.sortBy[0].property").value("id")) .andExpect(jsonPath("$.sort.sortBy[0].direction").value("ASC")); }
3. 用Jackson将响应转成Page对象断言
如果需要更复杂的验证(比如检查具体User对象内容),可以将响应JSON转成Page<User>:
import org.springframework.test.web.servlet.MvcResult; import com.fasterxml.jackson.core.type.TypeReference; @Test void testUserPageContent() throws Exception { MvcResult result = mockMvc.perform(get("/users") .param("page", "0") .param("size", "10")) .andExpect(status().isOk()) .andReturn(); // 将响应转成Page<User> Page<User> userPage = objectMapper.readValue( result.getResponse().getContentAsString(), new TypeReference<Page<User>>() {} ); // 断言分页属性 assertEquals(10, userPage.getSize()); assertEquals(100, userPage.getTotalElements()); assertEquals("id", userPage.getSort().stream().findFirst().get().getProperty()); // 断言具体用户内容 assertEquals("testUser1", userPage.getContent().get(0).getUsername()); }
4. 检查依赖兼容性
确保spring-data-commons和jackson-databind版本与Spring 3.4.1兼容,Java 21建议使用Jackson 2.17+版本:
<!-- Maven依赖示例 --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-commons</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.2</version> </dependency>
内容的提问来源于stack exchange,提问作者CoderJammer
相关产品推荐
相关产品推荐

