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 메서드를 통해 사용자 정보를 설정해주어서, 테스트가 잘 작동할 수 있었다.