【问题标题】:Integration test fails when testing @NotNull测试 @NotNull 时集成测试失败
【发布时间】:2017-03-29 07:48:14
【问题描述】:

我克隆了this project 并将Hotel.java 更改为:

@Entity
public class Hotel implements Serializable {
  .
  .
  @javax.validation.constraints.NotNull
//@Column(nullable = false)
  private String address;
  .
  .
}

当发出类似这样的帖子请求时:

curl -H "Content-Type: application/json" -X POST -d '{}' http://localhost:8080/api/hotels

回复是:

{
  "timestamp": 1479213670718,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "javax.validation.ConstraintViolationException",
  "message": "org.springframework.web.util.NestedServletException:   Request processing failed; nested exception is javax.validation.ConstraintViolationException: Validation failed for classes [sample.data.rest.domain.Hotel] during persist time for groups [javax.validation.groups.Default, ]\nList of constraint violations:[\n\tConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=address, rootBeanClass=class sample.data.rest.domain.Hotel, messageTemplate='{javax.validation.constraints.NotNull.message}'}\n]",
  "path": "/api/hotels"
}

然后我为这个案例写了测试:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("scratch")
public class SampleDataRestApplicationTests {
  .
  .

  @Test
  public void createHotel_andExpectServerError() throws Exception {
    this.mvc.perform(post("/api/hotels").content("{}"))
            .andExpect(status().is5xxServerError());
  }

}

当我运行测试时,它会抛出这个错误:

org.springframework.web.util.NestedServletException: 
Request processing failed; nested exception is javax.validation.ConstraintViolationException: 
Validation failed for classes [sample.data.rest.domain.Hotel] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
  ConstraintViolationImpl{
    interpolatedMessage='may not be null', 
    propertyPath=address, rootBeanClass=class sample.data.rest.domain.Hotel, 
    messageTemplate='{javax.validation.constraints.NotNull.message}'}
]

所以它失败了,但我希望它会通过。

似乎处理 ConstraintViolationException 的默认 exceptionHandler 通常在测试中不可用。

谢谢。

【问题讨论】:

    标签: java spring-boot integration-testing spring-data-jpa


    【解决方案1】:

    我无法重现您的结果,但也许可以通过澄清一些事情来更接近您的问题。

    如果我在我的机器上执行你的 curl 命令(带有一个额外的 -v 标志来获取标题),我会收到一个客户端错误,确切地说是409 Conflict

    curl -v -H "Content-Type: application/json" -X POST -d '{}' http://localhost:8080/api/hotels
    Note: Unnecessary use of -X or --request, POST is already inferred.
    *   Trying 127.0.0.1...
    * Connected to localhost (127.0.0.1) port 8080 (#0)
    > POST /api/hotels HTTP/1.1
    > Host: localhost:8080
    > User-Agent: curl/7.47.0
    > Accept: */*
    > Content-Type: application/json
    > Content-Length: 2
    > 
    * upload completely sent off: 2 out of 2 bytes
    < HTTP/1.1 409 Conflict
    < Date: Sun, 22 Jan 2017 12:29:45 GMT
    < Content-Type: application/hal+json;charset=UTF-8
    < Transfer-Encoding: chunked
    < 
    * Connection #0 to host localhost left intact
    {"cause":{"cause":{"cause":null,"message":"NULL not allowed for column \"ADDRESS\"; SQL statement:\ninsert into hotel (id, address, city_id, name, zip) values (null, ?, ?, ?, ?) [23502-193]"},"message":"could not execute statement"},"message":"could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement"}
    

    在我的 IDE (STS) 中执行测试也是如此:

    java.lang.AssertionError: Range for response status value 409 expected:<SERVER_ERROR> but was:<CLIENT_ERROR>
        at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)
        at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)
        at org.springframework.test.web.servlet.result.StatusResultMatchers$7.match(StatusResultMatchers.java:132)
        at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)
        ...
    

    所以起初测试和正在运行的应用程序之间没有区别,DataIntegrityViolationException / ConstraintViolationException 在两种情况下都映射到 409。

    如果正确是另一个问题,但可能发送错误/无效数据实际上是客户端错误。

    如果你仍然想改变它,你必须添加你自己的 ExceptionHandler 可能是这样的:

    import org.hibernate.exception.ConstraintViolationException;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.context.request.WebRequest;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
    
    @RestControllerAdvice
    public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler {
    
        @ExceptionHandler({ ConstraintViolationException.class })
        public ResponseEntity<Object> handleConstraintViolationException(Exception ex, WebRequest request) {
            return handleExceptionInternal(ex, "I think it's the servers fault!", new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
        }
    
    }
    

    也许这可以解决您的问题,分别。给你一个提示。还是我没有得到其他问题?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-28
      • 2019-12-26
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 2016-11-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多