Spring 6.1 Rendering Page对象无法按预期工作

2ic8powd  于 2023-09-29  发布在  Spring
关注(0)|答案(1)|浏览(176)

我尝试将我的示例项目升级到Spring 6.1.0-M4,但由于渲染Page对象,一些测试失败。

  • 它与旧的Spring 6.0.10* 工作得很好,我不确定是否需要额外的配置。
  1. @RequiredArgsConstructor
  2. @RestController
  3. @RequestMapping("/posts")
  4. @Validated
  5. public class PostController {
  6. private final PostRepository posts;
  7. @GetMapping(value = "", produces = APPLICATION_JSON_VALUE)
  8. public ResponseEntity<Page<PostSummary>> getAll(@RequestParam(defaultValue = "") String q,
  9. @RequestParam(defaultValue = "") String status,
  10. @RequestParam(defaultValue = "0") int page,
  11. @RequestParam(defaultValue = "10") int size) {
  12. var postStatus = StringUtils.hasText(status) ? Status.valueOf(status) : null;
  13. var data = this.posts.findAll(Specifications.findByKeyword(q, postStatus), PageRequest.of(page, size))
  14. .map(p -> new PostSummary(p.getTitle(), p.getCreatedAt()));
  15. return ok(data);
  16. }

测试代码看起来像。

  1. @SpringJUnitWebConfig(classes = {Jackson2ObjectMapperConfig.class, WebConfig.class, TestDataConfig.class})
  2. @ActiveProfiles("test")
  3. public class PostControllerTestWithMockMvcWebTestClient {
  4. @Autowired
  5. PostController ctrl;
  6. WebTestClient rest;
  7. @Autowired
  8. PostRepository posts;
  9. @BeforeEach
  10. public void setup() {
  11. this.rest = MockMvcWebTestClient
  12. .bindToController(ctrl)
  13. .dispatcherServletCustomizer(dispatcherServlet -> dispatcherServlet.setEnableLoggingRequestDetails(true))
  14. .configureClient()
  15. .build();
  16. }
  17. @Test
  18. public void getAllPostsWillBeOk() throws Exception {
  19. when(this.posts.findAll(isA(Specification.class), isA(Pageable.class)))
  20. .thenReturn(new PageImpl<>(
  21. List.of(
  22. Post.builder().title("test").content("content of test1").build(),
  23. Post.builder().title("test2").content("content of test2").build()
  24. )
  25. )
  26. );
  27. this.rest
  28. .get()
  29. .uri("/posts")
  30. .exchange()
  31. .expectStatus().isOk();
  32. // .expectBody().jsonPath("$.totalElements").isEqualTo(2);
  33. verify(this.posts, times(1)).findAll(isA(Specification.class), isA(Pageable.class));
  34. verifyNoMoreInteractions(this.posts);
  35. }
  36. }

最后我得到了这样的例外。

  1. 2023-08-22 13:25:10,579 DEBUG [main] org.springframework.core.log.LogFormatUtils: Writing [Page 1 of 1 containing com.example.demo.web.PostSummary instances]
  2. 2023-08-22 13:25:10,638 WARN [main] org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver: Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.UnsupportedOperationException)]
  3. 2023-08-22 13:25:10,666 DEBUG [main] org.springframework.core.log.LogFormatUtils: [4b544732] HTTP GET /posts
  4. 2023-08-22 13:25:10,676 DEBUG [main] org.springframework.core.log.LogFormatUtils: [4b544732] [21abda60] Response 500 INTERNAL_SERVER_ERROR
  5. 2023-08-22 13:25:10,745 ERROR [main] org.springframework.test.web.reactive.server.ExchangeResult: Request details for assertion failure:
  6. > GET /posts
  7. > WebTestClient-Request-Id: [1]
  8. No content
  9. < 500 INTERNAL_SERVER_ERROR Internal Server Error
  10. < Content-Type: [application/json]
  11. {"content":[{"title":"test","createdAt":null},{"title":"test2","createdAt":null}],"pageable":{"sort":{"empty":true,"sorted":false,"unsorted":true}}}
  12. ====================== MockMvc (Server) ===============================
  13. MockHttpServletRequest:
  14. HTTP Method = GET
  15. Request URI = /posts
  16. Parameters = {}
  17. Headers = [WebTestClient-Request-Id:"1"]
  18. Body = <no character encoding set>
  19. Session Attrs = {}
  20. Handler:
  21. Type = com.example.demo.web.PostController
  22. Method = com.example.demo.web.PostController#getAll(String, String, int, int)
  23. Async:
  24. Async started = false
  25. Async result = null
  26. Resolved Exception:
  27. Type = org.springframework.http.converter.HttpMessageNotWritableException
  28. ModelAndView:
  29. View name = null
  30. View = null
  31. Model = null
  32. FlashMap:
  33. Attributes = null
  34. MockHttpServletResponse:
  35. Status = 500
  36. Error message = null
  37. Headers = [Content-Type:"application/json"]
  38. Content type = application/json
  39. Body = {"content":[{"title":"test","createdAt":null},{"title":"test2","createdAt":null}],"pageable":{"sort":{"empty":true,"sorted":false,"unsorted":true}}}
  40. Forwarded URL = null
  41. Redirected URL = null
  42. Cookies = []
  43. java.lang.AssertionError: Status expected:<200 OK> but was:<500 INTERNAL_SERVER_ERROR>
  44. Expected :200 OK
  45. Actual :500 INTERNAL_SERVER_ERROR
  46. <Click to see difference>
  47. at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:59)
  48. at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:122)
  49. at org.springframework.test.web.reactive.server.StatusAssertions.lambda$assertStatusAndReturn$4(StatusAssertions.java:236)
  50. at org.springframework.test.web.reactive.server.ExchangeResult.assertWithDiagnostics(ExchangeResult.java:222)
  51. at org.springframework.test.web.reactive.server.StatusAssertions.assertStatusAndReturn(StatusAssertions.java:236)
  52. at org.springframework.test.web.reactive.server.StatusAssertions.isOk(StatusAssertions.java:68)
  53. at com.example.demo.web.PostControllerTestWithMockMvcWebTestClient.getAllPostsWillBeOk(PostControllerTestWithMockMvcWebTestClient.java:63)
  54. at java.base/java.lang.reflect.Method.invoke(Method.java:568)
  55. at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
  56. at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

示例项目代码如下:https://github.com/hantsy/spring6-sandbox/tree/master/data-jpa

4dbbbstv

4dbbbstv1#

在新的Spring Data中,new PageImpl(data)将使用一个新的UnPaged类来组装页面数据,而这个异常是由UnPaged.getOffset()方法引发的。
简单地说,我们可以使用一个自定义类来表示分页的结果,例如:

  1. public record PaginatedResult<T>(List<T> data, Long count){}

然后在控制器中尝试将返回的Page<T>转换为PaginatedResult<T>

  1. new PaginatedResult(page.getContent(), page.getTotalElementCount());

在测试代码中,控制器将返回如下响应体:

  1. new PaginatedResult(
  2. listOf(...),
  3. count
  4. );

相关问题