当前位置: 首页 > 知识库问答 >
问题:

Spring boot-test-validator:无效的验证器目标

高展
2023-03-14

当我试图运行一个测试时,我得到以下错误:

org.springframework.web.util.NestedServletException:请求处理失败;嵌套异常为java.lang.IllegalStateException:验证器[userCreateFormValidator bean]的目标无效:com.ar.empresa.forms.UserCreateForm@15C3585

原因:java.lang.IllegalStateException:验证器[userCreateFormValidator bean]的目标无效:com.ar.empresa.forms.UserCreateForm@15c3585在org.springframework.validation.databinder.assertValidators(databinder.java:567)在org.springframework.validation.databinder.addValidators(databinder.java:578)在

代码为:

控制器:

@Controller
public class UserController {
private UserService userService;
private UserCreateFormValidator userCreateFormValidator;

@Autowired
public UserController(UserService userService, UserCreateFormValidator userCreateFormValidator) {
    this.userService = userService;
    this.userCreateFormValidator = userCreateFormValidator;
}

@InitBinder("form")
public void initBinder(WebDataBinder binder) {
    binder.addValidators(userCreateFormValidator);
}

@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(value = "/user/create", method = RequestMethod.GET)
public ModelAndView getUserCreatePage() {
    return new ModelAndView("user_create", "form", new UserCreateForm());
}

@PreAuthorize("hasAuthority('ADMIN')")
@RequestMapping(value = "/user/create", method = RequestMethod.POST)
public String handleUserCreateForm(@Valid @ModelAttribute("form") UserCreateForm form, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return "user_create";
    }
    try {
        userService.create(form);
    } catch (DataIntegrityViolationException e) {
        bindingResult.reject("email.exists", "Email already exists");
        return "user_create";
    }
    return "redirect:/users";
}
}

验证器:

@Component
public class UserCreateFormValidator implements Validator {

private final UserService userService;

@Autowired
public UserCreateFormValidator(UserService userService) {
    this.userService = userService;
}

@Override
public boolean supports(Class<?> clazz) {
    return clazz.equals(UserCreateForm.class);
}

@Override
public void validate(Object target, Errors errors) {
    UserCreateForm form = (UserCreateForm) target;
    validatePasswords(errors, form);
    validateEmail(errors, form);
}

private void validatePasswords(Errors errors, UserCreateForm form) {
    if (!form.getPassword().equals(form.getPasswordRepeated())) {
        errors.reject("password.no_match", "Passwords do not match");
    }
}

private void validateEmail(Errors errors, UserCreateForm form) {
    if (userService.getUserByEmail(form.getEmail()).isPresent()) {
        errors.reject("email.exists", "User with this email already exists");
    }
}
}

UserCreateForm:

public class UserCreateForm {

@NotEmpty
private String email = "";

@NotEmpty
private String password = "";

@NotEmpty
private String passwordRepeated = "";

@NotNull
private Role role = Role.USER;

public String getEmail() {
    return email;
}

public String getPassword() {
    return password;
}

public String getPasswordRepeated() {
    return passwordRepeated;
}

public Role getRole() {
    return role;
}

public void setEmail(String email) {
    this.email = email;
}

public void setPassword(String password) {
    this.password = password;
}

public void setPasswordRepeated(String passwordRepeated) {
    this.passwordRepeated = passwordRepeated;
}

public void setRole(Role role) {
    this.role = role;
}
}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserControllerTest {

private MockMvc mockMvc;

private MediaType contentType = new MediaType(APPLICATION_JSON.getType(),
        APPLICATION_JSON.getSubtype(),
        Charset.forName("utf8"));

@MockBean
private UserService userService;

@MockBean
private UserCreateFormValidator userCreateFormValidator;

@Autowired
FilterChainProxy springSecurityFilterChain;

@Before
public void setup() {
    this.mockMvc = MockMvcBuilders.standaloneSetup(new UserController(userService,userCreateFormValidator)).apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain)).build();
}

@Test
@WithMockUser(username="user",
        password="password",
        roles="ADMIN")
public void homePage_authenticatedUser() throws Exception {
    mockMvc.perform(get("/user/create"))
            .andExpect(status().isOk())
            .andExpect(view().name("user_create"));
}
}

我不知道为什么,因为它是一个GET方法,所以它不必验证它。谢谢!:)

共有1个答案

黄骏喆
2023-03-14

出现此异常是因为您没有在UserCreateFormValidator@mockbean上模拟公共布尔支持(类<?>clazz)方法的行为。如果您从发布的日志中查看org.springframework.validation.databinder.assertvalidators(databinder.java)的代码,您可以在那里找到验证器是如何处理的,以及java.lang.IllegalStateException是如何抛出的。在Spring 4.3.8中,它如下所示

if(validator != null && this.getTarget() != null && !validator.supports(this.getTarget().getClass())) {
    throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + this.getTarget());
}

您没有模拟验证器的supports方法,默认情况下返回false,导致上面的Spring代码抛出IllegalStateException

TLDR,给我一个解决方案:

您必须在验证器上模拟supports方法。向@before@beforeclass方法添加以下内容。

when(requestValidatorMock.supports(any())).thenReturn(true);
 类似资料:
  • 作用 验证给定字符串是否满足指定条件,一般用在表单字段验证里。 此类中全部为静态方法。 使用 判断验证 直接调用Validator.isXXX(String value)既可验证字段,返回是否通过验证。 例如: boolean isEmail = Validator.isEmail("loolly@gmail.com") 表示验证给定字符串是否复合电子邮件格式。 其他验证信息请参阅Validat

  • JSF提供内置验证器来验证其UI组件。 这些标签可以验证字段的长度,输入的类型可以是自定义对象。 对于这些标记,您需要在html节点中使用以下URI名称空间。 <html xmlns = "http://www.w3.org/1999/xhtml" xmlns:f = "http://java.sun.com/jsf/core" > 以下是JSF 2.0中重要的Validat

  • 大家好,每当我尝试在Spring调用验证器时,我都会收到以下错误 请看看并帮助我解决这个错误,以前我使用登录页面的验证,它工作正常,但现在它不工作。 这是我的代码片段。 控制器 } 验证器 JSP页面

  • 本文向大家介绍详解vue-validator(vue验证器),包括了详解vue-validator(vue验证器)的使用技巧和注意事项,需要的朋友参考一下 官方文档:http://vuejs.github.io/vue-validator/zh-cn/index.html github项目地址:https://github.com/vuejs/vue-validator 单独使用vue-valid

  • 我们可以在JSF中创建自己的Custom验证器。 在JSF中定义自定义验证器分为三个步骤。 步 描述 1 通过实现javax.faces.validator .Validator接口创建验证器类。 2 实现上述接口的validate()方法。 3 使用注释@FacesValidator为自定义验证程序分配唯一ID。 步骤1:创建Validator类:UrlValidator.java public

  • Jboot 从 V3.7.5 开始,增强 Jboot 的验证方式,在 Jboot 之前的 @EmptyValidate、@RegexValidate 等基础上,进一步基于 JSR 303 – Bean Validation 简化了验证方式,相比 Spring 更加优雅简单。 @NotNull 在 Controller (或 Service 等)中,我们可以直接通过 @NotNull 注解给 Con