• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

AccountControllerTest 실행오류

21.12.08 01:56 작성 조회수 659

0

안녕하세요.

알려주신대로 index 메서드의 두번째 파라미터에@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account") Account account를 넣은 이후, AccountControllerTest를 돌렸을 때, 아래와 같은 오류가 나오고있는 상황입니다. @AuthenticationPrincipal UserAccount userAccount를 두번째 파라미터로 넣으면 잘 동작합니다.

@GetMapping("/")
public String index(Model model, @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account") Account account) {
    if ( account == null ) {
        model.addAttribute("message", "Hello Spring Security");
    } else {
        model.addAttribute("message", "Hello, " + account.getUsername());
    }

    return "index";
}

오류 로그

Request processing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'account' cannot be found on object of type 'org.springframework.security.core.userdetails.User' - maybe not public or not valid?org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'account' cannot be found on object of type 'org.springframework.security.core.userdetails.User' - maybe not public or not valid?

 

이 경우, 테스트 코드를 바꿔줘야 할 부분이 있는건가요??

바쁘시겠지만 확인해주시면 감사하겠습니다.

답변 1

답변을 작성해보세요.

1

Property or field 'account' cannot be found on object of type 'org.springframework.security.core.userdetails.User

이 에러를 보니까 아마도 UserDetailsService 구현체에서 User를 리턴하신것 같네요. User가 아니라 Account를 담고 있는 커스텀한 타입의 User를 리턴해야 할 것 같습니다. UserDetailsService 구현체 코드를 점검해 보셔야 할 것 같습니다.

nmnnhlba님의 프로필

nmnnhlba

질문자

2021.12.11

이상하네요. 저도 그렇게 인지하고 loadByUsername 메서드에 아래와 같이 UserAccount 인스턴스를 리턴할 수 있도록 작성했는데요. 어디에서 막히는지 도무지 감을 못잡겠네요.

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Account account = accountRepository.findByUsername(username);

    if ( account == null ) {
        throw new UsernameNotFoundException(username);
    }

    return new UserAccount(account);
}

테스트가 막히는 부분은 @WithAnonymousUser, @WithUser, @WithMockUser(username = "admin", roles = "ADMIN") 애노테이션을 사용한 테스트에서 막힙니다.

당연히 통과되어야할 것 같은 테스트인데 어느 부분에서 막히는지 감조차 안오네요.

도저히 답을 찾을 수 없을 것 같아 코드를 압축하여 공유해드립니다. 확인해주시면 감사하겠습니다.

https://drive.google.com/file/d/1eRsEY7wXaMLfwVTdOoX-VwVrVoVQBCBl/view?usp=sharing

@WithMockUser등을 사용할 때 기본적으로 커스텀하게 작성한 UserDetailsService의 구현체를 쓰지 않고 내부적으로 mocking 한 UDS를 쓰기 때문에 그런 문제가 발생합니다. 레퍼런스를 보시면, 커스텀한 UDS를 사용해야 하는 경우에 @WithUserDetails를 쓰는 방법을 소개하고 있습니다.

https://docs.spring.io/spring-security/site/docs/4.2.x/reference/html/test-method.html#test-method-withuserdetails

코드를 아래처럼 고치면 AccountSerivce를 사용해서 User를 찾으려고 하는것을 디버깅을 통해 알 수 있습니다. 다만, 문제는 이렇게 했을 때 해당 테스트에서 사용하는 유저 정인 admin이 없기 때문에 에러가 날 것입니다. 그 문제는 미리 해당 유저를 만든 다음에 테스트를 실행하도록 고쳐서 해결하실 수 있을겁니다.

@Test
@WithUserDetails(userDetailsServiceBeanName = "accountService")
@WithMockUser(username = "admin", roles = "ADMIN")
public void index_admin() throws Exception {
mockMvc.perform(get("/"))
.andDo(print())
.andExpect(status().isOk());
}