2017-03-05 56 views
3

我收到的時候我試圖運行測試以下錯誤無效的目標:春季啓動 - 測試 - 驗證:驗證爲

org.springframework.web.util.NestedServletException:請求處理失敗;嵌套異常是java.lang.IllegalStateException:無效目標驗證器[userCreateFormValidator豆]:java.lang.IllegalStateException:[email protected]

致無效目標驗證器[userCreateFormValidator bean]:[email protected] at org.springframework.validation.DataBinder.assertValidators(DataBinder.java:567) at org.springframework.validation.DataBinder.addValidators(DataBinder.java:578) 在com.ar.empresa.controllers.UserController.initBinder(UserController.java:36) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本機方法) 在sun.reflect.NativeMethodAccessorImpl。調用(NativeMethodAccessorImpl.java:62) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在java.lang.reflect.Method.invoke(Method.java:498)

的代碼是:

控制器:

@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"); 
    } 
} 
} 

UserCr eateForm:

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方法,所以它不必對其進行驗證。 謝謝! :)

回答

3

你有這個例外,因爲你沒有嘲笑你的userCreateFormValidator@Mockbeanpublic boolean supports(Class<?> 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,造成春代碼上面扔IllegalStateException

TLDR,只是給我的解決方案:

你要嘲笑你的驗證方法supports。將以下內容添加到@Before@BeforeClass方法中。

when(requestValidatorMock.supports(any())).thenReturn(true); 
+0

這個答案應該被接受! – Doug