验证Spring Boot控制器中HTTP POST请求中的请求主体是否为null [英] Validating if request body in HTTP POST request is null in Spring Boot controller

查看:422
本文介绍了验证Spring Boot控制器中HTTP POST请求中的请求主体是否为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在替换Spring Boot REST控制器中对POST请求的输入的手动验证。 JSR-303 Spring Bean验证用于验证请求正文中的实例变量,该方法按预期工作。建议使用什么方法来验证请求正文中的对象不为空?



我尝试过:




  • 注释整个对象,例如:@NotNull @Valid @RequestBody Foo foo


  • 注释整个类使用@NotNull




我要替换:

  @PostMapping ... 
public ResponseEntity< Map< String,Object>> editFoo(
@RequestBody Foo foo,...){
if(foo == null){
return(new ResponseEntity<>(headers,HttpStatus.BAD_REQUEST));
}
}

具有等效的Bean验证:

  @PostMapping ... 
public ResponseEntity< Map< String,Object>> editFoo(
@Valid @RequestBody Foo foo,...){
...
}

我尝试通过以下方式对控制器方法进行单元测试:

  / /安排
Foo foo = null;
字符串requestBody = objectMapper.writeValueAsString(foo);

//操作+断言
mockMvc
.perform(
post( / end_point)
.contentType( application / json)
.content(requestBody))
.andExpect(status()。isBadRequest());

我期望有一个MethodArgumentNotValidException,该异常由@ControllerAdvice处理,但是执行时我得到HttpMessageNotReadableException单元测试。
我的问题:


  1. 是否有必要测试请求正文是否为空?

  2. 如果1.是真实的,该如何通过Bean验证来完成?


解决方案

看到您的代码,您已经检查了主体是否为null。实际上, @RequestBody 具有默认参数 required ,该参数默认为true。因此,不需要为此进行Bean验证!



您的主要问题似乎在测试中。首先,最好编写一个测试以验证您的端点行为是否为空。



但是,在测试中您不会通过null。您尝试使用 objectMapper null 值创建Json对象。
您正在编写的对象似乎不是有效的json。因此,当您发送此正文时,Spring表示它无法读取消息,也就是您的请求的正文,因为您说它是 application / json 内容,但没有



要测试空主体,只需在测试中发送您的请求,只需删除 .content(requestBody)行,它应该可以工作!立即为我工作。这是我的控制程序和测试程序,因此您可以将其与完整代码进行比较:

  @RestController()
@RequestMapping( end_point)
公共类TestController {

@PostMapping
public ResponseEntity< Map< String,Object> editFoo(@RequestBody Foo foo){
// if(foo == null){
// return(new ResponseEntity<>(new HashMap<>(),HttpStatus.BAD_REQUEST));
//}

返回(新的ResponseEntity<>(新的HashMap<>(),HttpStatus.OK));
}
}


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
公共类TestControllerTest {
@Autowired
private MockMvc mvc;

@Autowired
私人ObjectMapper objectMapper;

@Test
public void test_body_is_null()引发异常{

Foo foo = null;
字符串requestBody = objectMapper.writeValueAsString(foo);

//操作+断言
mvc
.perform(
post( / end_point)
.contentType( application / json)
.content(requestBody))
.andExpect(status()。isBadRequest());
}
}

这是使用Spring Boot 2.1.6制作的。



---编辑2
作为记录,如果您想在此处使用验证为null,则是控制器的代码段:

  @RestController()
@RequestMapping( end_point)
@Validated
公共类TestController {

@PostMapping
public ResponseEntity< Map< String,Object>> editFoo(@NotNull @RequestBody(required = false)Foo foo){

return(new ResponseEntity<>(new HashMap<>(),HttpStatus.OK));
}
}

首先,您必须将身体设置为false ,默认为true。然后,您必须在请求正文上添加 @NotNull 批注,并在控制器上添加 @Validated
在这里,如果您启动测试,您将看到请求失败,并显示以下内容:

  org.springframework.web.util .NestedServletException:请求处理失败;嵌套异常是javax.validation.ConstraintViolationException:editFoo.foo:不能为空

有了 @ControllerAdvice ,您可以根据需要映射异常!


I am replacing manual validation of input to a POST request in a Spring Boot REST-controller. JSR-303 Spring Bean Validation is used for validating the instance variables in the request body and this is working as expected. What is the recommended method to validate that the object in the request body is not null?

I have tried:

  • annotating the entire object such as this: @NotNull @Valid @RequestBody Foo foo

  • annotating the entire class with @NotNull

I am replacing:

@PostMapping...
public ResponseEntity<Map<String, Object>> editFoo(
@RequestBody Foo foo, ...) {
   if(foo == null) {
      return (new ResponseEntity<>(headers, HttpStatus.BAD_REQUEST));
   }
}

with a Bean Validation equivalent:

@PostMapping...
public ResponseEntity<Map<String, Object>> editFoo(
@Valid @RequestBody Foo foo, ...) {
   ...
}

I tried unit testing the controller method by:

// Arrange
    Foo foo = null;
    String requestBody = objectMapper.writeValueAsString(foo);

    // Act + assert
    mockMvc
    .perform(
    post("/end_point")
    .contentType("application/json")
    .content(requestBody))
    .andExpect(status().isBadRequest());

I expected a MethodArgumentNotValidException which is handled by a @ControllerAdvice for this exception, but I get HttpMessageNotReadableException when executing the unit test. My questions:

  1. is it necessary to test if the request body is null?
  2. if 1. is true, how should this be done with Bean Validation?

解决方案

Seeing your code, you already check if the body is null. In fact @RequestBody has a default parameter required which defaults to true. So no need for Bean validation for that !

Your main issue here seems to be in your test. First of all it is good to write a test to validate your endpoint behavior on null.

However, in your test you does not pass null. You try to create a Json object from a null value with your objectMapper. The object you are writting seems not to be a valid json. So when your sending this body, Spring says that it cannot read the message, aka the body of your request, as you say it is a application/json content but there is not json in it.

To test null body, just send your request in your test just removing the .content(requestBody) line and it should work !

--- Edit 1 I thought it was rejecting the message because of the body, but in fact it seems to work right away for me. Here is my controler and test so you can compare to your full code :

@RestController()
@RequestMapping("end_point")
public class TestController {

    @PostMapping
    public ResponseEntity<Map<String, Object>> editFoo(@RequestBody Foo foo) {
       // if(foo == null) {
       //     return (new ResponseEntity<>(new HashMap<>(), HttpStatus.BAD_REQUEST));
       // }

        return (new ResponseEntity<>(new HashMap<>(), HttpStatus.OK));
    }
}


@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
public class TestControllerTest {
    @Autowired
    private MockMvc mvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void test_body_is_null() throws Exception {

        Foo foo = null;
        String requestBody = objectMapper.writeValueAsString(foo);

        // Act + assert
        mvc
            .perform(
                post("/end_point")
                    .contentType("application/json")
                    .content(requestBody))
            .andExpect(status().isBadRequest());
    }
}

This was made using Spring Boot 2.1.6.RELEASE

--- Edit 2 For the record if you want to use validation for null here, here is a snippet of the controller :

@RestController()
@RequestMapping("end_point")
@Validated
public class TestController {

    @PostMapping
    public ResponseEntity<Map<String, Object>> editFoo(@NotNull @RequestBody(required = false) Foo foo) {

        return (new ResponseEntity<>(new HashMap<>(), HttpStatus.OK));
    }
}

First you have to set required to false for the body, as default is true. Then you have to add the @NotNull annotation on the request body and @Validated on the controller. Here if you launch your test you will see that the request fails with :

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ConstraintViolationException: editFoo.foo: must not be null

As you said you had a @ControllerAdvice you can then map the exception as you wish !

这篇关于验证Spring Boot控制器中HTTP POST请求中的请求主体是否为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆