【问题标题】:How to test @Valid如何测试@Valid
【发布时间】:2012-12-06 14:36:06
【问题描述】:

在我的实体中,我有一些用于验证的休眠注释,例如 @NotEmpty、@Pattern.. 等

在我的控制器中,在保存操作时,它有一个 @Valid 参数。

但是如果任何实体有任何必填字段,并且没有注释我会遇到问题。

所以我想测试每个实体,以确保它们有必要的注释。

类似:

@Test(expect=IllegalArgumentException.class)
public void testAllNull() {
    Person p = new Persson(); // Person name has an @NotEmpty
    validator.validate(p);
}

但是如何验证呢?调用谁来检查@Valid?

谢谢。

【问题讨论】:

    标签: junit annotations hibernate-annotations spring-annotations


    【解决方案1】:

    我发现了如何检查:

        @Autowired
        private LocalValidatorFactoryBean validator;
    
        ...
    
        validator.validateProperty(object, propertyName)
    

    【讨论】:

      【解决方案2】:

      这是一个基于 Spring v4.1.x 的测试示例,用于验证 @Valid 注释的存在和处理以及在发生错误时构建自定义 JSON 响应。

      jUnit

      import com.fasterxml.jackson.core.type.TypeReference;
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.context.annotation.Bean;
      import org.springframework.http.MediaType;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
      import org.springframework.test.web.servlet.MockMvc;
      import org.springframework.test.web.servlet.MvcResult;
      import org.springframework.test.web.servlet.setup.MockMvcBuilders;
      
      import javax.inject.Inject;
      import java.util.List;
      
      import static org.abtechbit.miscboard.util.JsonUtils.toJson;
      import static org.hamcrest.CoreMatchers.is;
      import static org.hamcrest.CoreMatchers.notNullValue;
      import static org.junit.Assert.assertThat;
      import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
      import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
      import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
      
      @RunWith(SpringJUnit4ClassRunner.class)
      @ContextConfiguration(classes = {
              RegistrationValidationTest.MockDependencies.class,
      })
      public class RegistrationValidationTest {
      
          @Inject
          MockMvc mvc;
      
          @Test
          public void validatesRegistration() throws Exception {
              Registration registration = ... //build an invalid Registration object
              MvcResult result = mvc.perform(post(RegistrationController.CONTEXT_REGISTER).
                      contentType(MediaType.APPLICATION_JSON).
                      content(toJson(registration))).
                      andExpect(status().isBadRequest()).
                      andExpect(content().contentType(MediaType.APPLICATION_JSON)).
                      andReturn();
      
              assertThat(result.getResolvedException(), is(notNullValue()));
              String content = result.getResponse().getContentAsString();
              assertThat(content, is(notNullValue()));
              List<Message> messages = JsonUtils.fromJson(content, new TypeReference<List<Message>>() {
              });
              assertThat(messages.size(), is(1));
          }
      
          public static class MockDependencies {
      
              @Bean
              public MockMvc mvc() {
                  return MockMvcBuilders.standaloneSetup(new RegistrationController()).build();
              }
          }
      }
      

      控制器

      import org.springframework.http.HttpStatus;
      import org.springframework.http.MediaType;
      import org.springframework.http.ResponseEntity;
      import org.springframework.stereotype.Controller;
      import org.springframework.web.bind.MethodArgumentNotValidException;
      import org.springframework.web.bind.annotation.*;
      
      import javax.validation.Valid;
      import java.util.List;
      import java.util.stream.Collectors;
      
      @Controller
      public class RegistrationController
      {
          public static final String CONTEXT_REGISTER = "/register";
      
          @RequestMapping(value = CONTEXT_REGISTER, method = RequestMethod.POST)
          @ResponseBody
          public String register(@RequestBody @Valid Registration registration) {
              //perform registration
          }
      
          @ExceptionHandler(MethodArgumentNotValidException.class)
          public ResponseEntity<List> handleValidationException(MethodArgumentNotValidException ex) {
              //Build a list of custom Message{String message;} objects
              List<Message> messages = ex.getBindingResult().getAllErrors().
                      stream().map(e->new Message(e.getDefaultMessage())).collect(Collectors.toList());
              return ResponseEntity.status(HttpStatus.BAD_REQUEST).contentType(MediaType.APPLICATION_JSON).body(messages);
          }
      }
      

      【讨论】:

        【解决方案3】:

        Spring MVC Test Framework 可能是一个不错的选择。通过使用它,您可以确保测试中的验证运行代码,因为 Spring @MVC 实际工作。

        其实@Valid注解是被HandlerMethodInvoker检测到的,它处理Spring控制器的handler方法上的注解。在内部,实际的验证逻辑被委托给Validator bean,具体取决于您的应用程序上下文设置。 (Hibernate Validator 被广泛使用。)

        在默认配置下(例如&lt;mvc:annotation-driven /&gt;),LocalValidatorFactoryBean 在内部用于处理@Valid 注释,正如@Falci 所指出的那样,但有时可能会有所不同。相反,Spring MVC 测试框架提供了与主应用程序相同的环境,因此是一个不错的选择。

        【讨论】:

          猜你喜欢
          • 2023-03-26
          • 2017-12-12
          • 2018-03-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-02-20
          • 2021-04-08
          相关资源
          最近更新 更多