在可分页控制器上使用 WebTestClient
Use WebTestClient on a Pageable Controller
我正在使用 Spring Boot 2 附带的反应式 Web 测试替代方案,并且我正在尝试为这样的控制器构建测试:
@RestController
@RequestMapping("/users")
public class UserController{
@Autowired
private UserService service;
@GetMapping
public Page<UserDTO> get(Pageable pageable){
return service.get(pageable);
}
}
测试看起来像这样:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UsersTest{
@Autowired
private WebTestClient webClient;
@Test
public void test(){
List<UserDTO> userList = webClient.get()
.uri("/users")
.exchange()
.expectStatus().isOk()
.expectBodyList(UserDTO.class).hasSize(1)
.returnResult()
.getResponseBody();
assertNotNull(userList.get(1).getId());
}
}
请求中的结果实际上是一个包含 1 个元素的列表,但不正确,因为响应的结构是:
{
"content": [
{
"id": 1,
"name": "John",
"lastName": "Doe",
"active": true
}
],
"pageable": {
"sort": {
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageSize": 25,
"pageNumber": 0,
"unpaged": false,
"paged": true
},
"totalPages": 1,
"totalElements": 1,
"last": true,
"size": 25,
"number": 0,
"numberOfElements": 1,
"first": true,
"sort": {
"sorted": false,
"unsorted": true
}
}
所以当我得到第一个元素的 id 值时,我得到了一个空值。并且测试失败。
是否有一种方法(可能是 Exchange 过滤器功能)使 WebTestClient 理解可分页的响应?
在此先感谢您的帮助。
我认为 WebTestClient 可以理解可分页的响应。
响应的结构是 json,WebTestClient 提供了一种与 json.
交互的方式
因此,如果您想测试响应是否包含 1 个具有 ID 的用户。你可以这样做:
webClient.get()
.uri("/users")
.exchange()
.expectBody()
.jsonPath("$.numberOfElements").isEqualTo(1)
.jsonPath("$.content[0].id").isNotEmpty();
我认为 Dirk Deyne 解决方案比我的好,但也许对某些人有用。
我使用 lombok:
构建了这 3 个 classes
@Data
@NoArgsConstructor
public class CustomResponsePage<T> {
List<T> content;
CustomPageable pageable;
Integer totalPages;
Integer totalElements;
Boolean last;
Integer size;
Integer number;
Long numberOfElements;
Boolean first;
CustomSort sort;
}
@Data
@NoArgsConstructor
public class CustomPageable{
CustomSort sort;
Long offset;
Integer pageSize;
Integer pageNumber;
Boolean unpaged;
Boolean paged;
}
@Data
@NoArgsConstructor
public class CustomSort {
Boolean sorted;
Boolean unsorted;
}
然后,我把测试修改成这样:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UsersTest{
@Autowired
private WebTestClient webClient;
@Test
public void test(){
PagedUserDTO pagedUserList = webClient.get()
.uri("/users")
.exchange()
.expectStatus().isOk()
.expectBody(UserDTO.class)
.returnResult(PagedUserDTO.class)
.getResponseBody();
assertTrue(pagedUserList.getContent().size() == 0);
}
private static class PagedUserDTO extends CustomResponsePage<UserDTO> { }
}
注意在测试结束时创建的 PagedUserDTO class。
这是一个仍在进行中的结构,因为它不考虑响应中何时有订单列,但在我的情况下我不需要它们。
我正在使用 Spring Boot 2 附带的反应式 Web 测试替代方案,并且我正在尝试为这样的控制器构建测试:
@RestController
@RequestMapping("/users")
public class UserController{
@Autowired
private UserService service;
@GetMapping
public Page<UserDTO> get(Pageable pageable){
return service.get(pageable);
}
}
测试看起来像这样:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UsersTest{
@Autowired
private WebTestClient webClient;
@Test
public void test(){
List<UserDTO> userList = webClient.get()
.uri("/users")
.exchange()
.expectStatus().isOk()
.expectBodyList(UserDTO.class).hasSize(1)
.returnResult()
.getResponseBody();
assertNotNull(userList.get(1).getId());
}
}
请求中的结果实际上是一个包含 1 个元素的列表,但不正确,因为响应的结构是:
{
"content": [
{
"id": 1,
"name": "John",
"lastName": "Doe",
"active": true
}
],
"pageable": {
"sort": {
"sorted": false,
"unsorted": true
},
"offset": 0,
"pageSize": 25,
"pageNumber": 0,
"unpaged": false,
"paged": true
},
"totalPages": 1,
"totalElements": 1,
"last": true,
"size": 25,
"number": 0,
"numberOfElements": 1,
"first": true,
"sort": {
"sorted": false,
"unsorted": true
}
}
所以当我得到第一个元素的 id 值时,我得到了一个空值。并且测试失败。
是否有一种方法(可能是 Exchange 过滤器功能)使 WebTestClient 理解可分页的响应?
在此先感谢您的帮助。
我认为 WebTestClient 可以理解可分页的响应。 响应的结构是 json,WebTestClient 提供了一种与 json.
交互的方式因此,如果您想测试响应是否包含 1 个具有 ID 的用户。你可以这样做:
webClient.get()
.uri("/users")
.exchange()
.expectBody()
.jsonPath("$.numberOfElements").isEqualTo(1)
.jsonPath("$.content[0].id").isNotEmpty();
我认为 Dirk Deyne 解决方案比我的好,但也许对某些人有用。
我使用 lombok:
构建了这 3 个 classes@Data
@NoArgsConstructor
public class CustomResponsePage<T> {
List<T> content;
CustomPageable pageable;
Integer totalPages;
Integer totalElements;
Boolean last;
Integer size;
Integer number;
Long numberOfElements;
Boolean first;
CustomSort sort;
}
@Data
@NoArgsConstructor
public class CustomPageable{
CustomSort sort;
Long offset;
Integer pageSize;
Integer pageNumber;
Boolean unpaged;
Boolean paged;
}
@Data
@NoArgsConstructor
public class CustomSort {
Boolean sorted;
Boolean unsorted;
}
然后,我把测试修改成这样:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class UsersTest{
@Autowired
private WebTestClient webClient;
@Test
public void test(){
PagedUserDTO pagedUserList = webClient.get()
.uri("/users")
.exchange()
.expectStatus().isOk()
.expectBody(UserDTO.class)
.returnResult(PagedUserDTO.class)
.getResponseBody();
assertTrue(pagedUserList.getContent().size() == 0);
}
private static class PagedUserDTO extends CustomResponsePage<UserDTO> { }
}
注意在测试结束时创建的 PagedUserDTO class。
这是一个仍在进行中的结构,因为它不考虑响应中何时有订单列,但在我的情况下我不需要它们。