SpringWebMvcTest - 使用@Valid 和自定义验证测试 Requestbody
SpringWebMvcTest - Test Requestbody using @Valid and custom validation
我正在尝试测试我的控制器端点和用 @Valid
注释注释的请求体。我的测试类如下所示:
@RunWith(SpringRunner.class)
@WebMvcTest(value = BalanceInquiryController.class, secure = false)
public class BalanceInquiryControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private BalanceInquiryController balanceInquiryController;
@Test
public void testGetBalanceInquiry() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/com/balanceInquiry")
.accept(MediaType.APPLICATION_JSON)
.content("{\"comGiftCard\":{\"cardNumber\":\"1234567890\",\"pinNumber\":\"0123\"},\"comMerchant\":\"MERCHANT1\"}")
.contentType(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
assertEquals(HttpStatus.OK.value(), response.getStatus());
}
}
我的控制器 - @PostMapping
看起来像这样:
@PostMapping(value = "/com/balanceInquiry")
public ResponseEntity<?> getBalanceInquiry(@Valid @RequestBody BalanceInquiryModel balanceInquiry, Errors errors) {
if (errors.hasErrors()) {
return new ResponseEntity<String>("Validation error", HttpStatus.BAD_REQUEST);
}
//do any stuff...
return new ResponseEntity<BalanceInquiryResponse>(balanceInquiryResponse, HttpStatus.OK);
}
我的 BalanceInquiryModel
带有 @Valid
注释,并且后面有一些休眠和自定义验证。这些验证都没有问题,并且已经过单元测试。
我想测试的是我发送一个有效的 json 请求体期望 200 响应和一个无效的 json 请求体期望 400 响应验证的端点通过集合 @Valid
实现。
例如,无效调用是不发送 pinNumber 或长度 < 4。
我已经阅读了一些线程和一些使用 MockMvcBuilders.standaloneSetup()
来模拟完整的控制器。但我不会做完整的集成测试。
不太确定如何继续这种情况以及我是否应该继续。
P.S.: 目前,无论验证是否应该给出错误,我总是得到 200 响应。
Here a gist 更多代码和验证 classes/models.
这是我在我的项目中工作的例子之一
希望对您有所帮助:
我有一个全局异常处理程序来处理我的 MethodArgumentNotValidException 并抛出它
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
}
public void testAdduser() throws Exception{
final User request = new User();
request.setFirstName("Test");
request.setLastName("some description");
mockMvc.perform(post(END_POINT+"/add")
.contentType(MediaType.APPLICATION_JSON)
.content(stringify(request))
).andDo(print()).andExpect(status().isUnprocessableEntity())
;
}
private String stringify(Object object) throws JsonProcessingException {
return new ObjectMapper().writeValueAsString(object);
}
更新:
我认为你的主要问题是你正在使用 @WebMvcTest 而不是 @SpringBootTest.
两者的区别在于:
@SpringBootTest 注释将加载完整的应用程序并注入所有可能很慢的 bean。
@WebMvcTest - 用于测试控制器层。它不会在 @RestController
旁边注入其他 bean
因此,如果您只是测试纯控制器以查看您是否可以到达终点,那么您可以使用@WebMvcTest,这将使您的测试 运行 更快。
但在你的情况下,你希望它运行 spring 验证,你将需要使用@SpringBootTest
我正在尝试测试我的控制器端点和用 @Valid
注释注释的请求体。我的测试类如下所示:
@RunWith(SpringRunner.class)
@WebMvcTest(value = BalanceInquiryController.class, secure = false)
public class BalanceInquiryControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private BalanceInquiryController balanceInquiryController;
@Test
public void testGetBalanceInquiry() throws Exception {
RequestBuilder requestBuilder = MockMvcRequestBuilders
.post("/com/balanceInquiry")
.accept(MediaType.APPLICATION_JSON)
.content("{\"comGiftCard\":{\"cardNumber\":\"1234567890\",\"pinNumber\":\"0123\"},\"comMerchant\":\"MERCHANT1\"}")
.contentType(MediaType.APPLICATION_JSON);
MvcResult mvcResult = mockMvc.perform(requestBuilder).andReturn();
MockHttpServletResponse response = mvcResult.getResponse();
assertEquals(HttpStatus.OK.value(), response.getStatus());
}
}
我的控制器 - @PostMapping
看起来像这样:
@PostMapping(value = "/com/balanceInquiry")
public ResponseEntity<?> getBalanceInquiry(@Valid @RequestBody BalanceInquiryModel balanceInquiry, Errors errors) {
if (errors.hasErrors()) {
return new ResponseEntity<String>("Validation error", HttpStatus.BAD_REQUEST);
}
//do any stuff...
return new ResponseEntity<BalanceInquiryResponse>(balanceInquiryResponse, HttpStatus.OK);
}
我的 BalanceInquiryModel
带有 @Valid
注释,并且后面有一些休眠和自定义验证。这些验证都没有问题,并且已经过单元测试。
我想测试的是我发送一个有效的 json 请求体期望 200 响应和一个无效的 json 请求体期望 400 响应验证的端点通过集合 @Valid
实现。
例如,无效调用是不发送 pinNumber 或长度 < 4。
我已经阅读了一些线程和一些使用 MockMvcBuilders.standaloneSetup()
来模拟完整的控制器。但我不会做完整的集成测试。
不太确定如何继续这种情况以及我是否应该继续。
P.S.: 目前,无论验证是否应该给出错误,我总是得到 200 响应。
Here a gist 更多代码和验证 classes/models.
这是我在我的项目中工作的例子之一 希望对您有所帮助:
我有一个全局异常处理程序来处理我的 MethodArgumentNotValidException 并抛出它
@RequestMapping(value = "/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
User savedUser = userService.save(user);
return new ResponseEntity<User>(savedUser, HttpStatus.CREATED);
}
public void testAdduser() throws Exception{
final User request = new User();
request.setFirstName("Test");
request.setLastName("some description");
mockMvc.perform(post(END_POINT+"/add")
.contentType(MediaType.APPLICATION_JSON)
.content(stringify(request))
).andDo(print()).andExpect(status().isUnprocessableEntity())
;
}
private String stringify(Object object) throws JsonProcessingException {
return new ObjectMapper().writeValueAsString(object);
}
更新:
我认为你的主要问题是你正在使用 @WebMvcTest 而不是 @SpringBootTest.
两者的区别在于:
@SpringBootTest 注释将加载完整的应用程序并注入所有可能很慢的 bean。
@WebMvcTest - 用于测试控制器层。它不会在 @RestController
旁边注入其他 bean因此,如果您只是测试纯控制器以查看您是否可以到达终点,那么您可以使用@WebMvcTest,这将使您的测试 运行 更快。
但在你的情况下,你希望它运行 spring 验证,你将需要使用@SpringBootTest