3
내가 테스트를 실행하기 위해 노력하고있어 다음과 같은 오류를 받고 있어요

잘못 대상 :봄 부팅 - 테스트 - 검사기 : 검사기

org.springframework.web.util.NestedServletException : 요청 처리가 실패; 검사기 [userCreateFormValidator 잘못된 타겟 잘못된 타겟 검사기 [userCreateFormValidator 빈]의 경우 : java.lang.IllegalStateException : [email protected]

에 의한 중첩 된 예외이다 java.lang.IllegalStateException bean] : [email protected] at org.springframework.validation.DataBinder.assertValidators (DataBinder.java:567) at org.springframework.validation.DataBinder.addValidators (DataBinder.java:578) at com.ar.empresa.controllers.UserController.initBinder (UserController.java:36) at sun.reflect.NativeMethodAccessorImpl.invoke0 (기본 메소드) at 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; 
} 
} 

테스트 : 그것은 GET 방식이기 때문에 그것을 검증 할 필요가 없습니다

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

내가 왜 모르겠어요. 감사합니다. :)

답변

3

userCreateFormValidator@Mockbeanpublic boolean supports(Class<?> clazz) 메서드의 동작을 조롱하지 않았으므로이 예외가 있습니다. 게시 한 로그에서 org.springframework.validation.DataBinder.assertValidators(DataBinder.java) 코드를 살펴보면 유효성 검사기가 처리되는 방법과 java.lang.IllegalStateException이 던져지는 방법을 찾을 수 있습니다. 당신은 봄 코드를 일으키는 원인이되는 검증의 supports 방법을 조롱 기본적으로 false를 반환하고 있지 않습니다

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

처럼 Spring 4.3.8에서는 위의 IllegalStateException을 던져 본다. 당신은 당신의 검증에 supports 방법을 조롱 할

:

TLDR, 그냥 나에게 솔루션을 제공합니다. @Before 또는 @BeforeClass 방법에 다음을 추가하십시오.

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

이 답변을 수락해야합니다! – Doug