Spring Security가 적용된 코드 테스트하는 법

smallcherry's techlog·2022년 8월 25일
0
post-custom-banner

프로그램 설명

환경

  • Springboot2.7.3, Java

인증인가 방식

  • JWT를 이용해 context에 등록된 토큰으로 현재 로그인한 사용자를 검증함.

검증하고자 하는 service 설명

  • 검증하고자 하는 서비스: calculateAndSaveHistory - 사용자를 확인하여 주어진 식을 계산한 뒤, 테이블에 사용자이름과 계산식, 정답과 정답여부를 insert하고, 사용자에게는 정답을 response한다.

문제점

  • calculateAndSaveHistory(dto)에서 테스트코드 작성에 문제가 되었던 부분은 아래와 같다.

    UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()
    										.getAuthentication().getPrincipal();
    String username = userDetails.getUsername();

    프로그램에선 username변수에 유저 이름을 저장하여, insert시 사용하지만 테스트 코드에서는SecurityContextHolder에서 유저 정보를 가져올때 Context에 토큰 정보가 저장되어 있지 않으므로 getAuthentication()에서 NPE 발생.

검증 방법

setUserToContextByUsername 메서드에 CustomerUserDetailsService에 만들어두었던 loadUserByUsername 메서드를 이용해 userDetails에 저장하고, context에 UsernamePasswordAuthentication 생성자를 통해 authentication을 지정해주었다.

    @Test
    void 계산후기록저장 () {
        //given
        CalculatorRequestDto requestDto = CalculatorRequestDto.builder().formula("1+3+(-6)/(-2)=3").build();

        //when
        setUserToContextByUsername("admin");
        calculatorService.calculateAndSaveHistory(requestDto).getCorrectAnswer();
        Double result = calculatorRepository.findByUsername("admin").get(0).getCorrectAnswer();

        //then
        Double expected = 7.0;
        assertThat(result.equals(result));
    }
	private void setUserToContextByUsername(String username) {
        CustomUserDetailsService customUserDetailsService = new CustomUserDetailsService(userRepository);
        UserDetails userDetails = customUserDetailsService.loadUserByUsername(username);
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities()));
    }

calculateAndSaveHistory메서드 call 전에 setUserToContextByUsername 메서드를 통해 사용자 정보를 설정해주어서, 테스트가 잘 작동할 수 있었다.

References

profile
Java Developer
post-custom-banner

0개의 댓글