我在Sping Boot 中基于Spring Security实现登录服务测试时遇到问题。我尝试在AuthService中实现登录方法,然后编写其服务方法,但我遇到了问题。
下面是问题显示
java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because "auth" is null
我该怎么修呢?
下面是JwtUserDetails类
@RequiredArgsConstructor
public class JwtUserDetails implements UserDetails {
private final User user;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRole roles = user.getUserRole();
List<SimpleGrantedAuthority> authories = new ArrayList<>();
authories.add(new SimpleGrantedAuthority(roles.name()));
return authories;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public long getId(){
return user.getId();
}
public String getEmail(){
return user.getEmail();
}
}
下面是AuthService
@Service
@RequiredArgsConstructor
public class AuthService{
private final AuthenticationManager authenticationManager;
private final JwtTokenProvider jwtTokenProvider;
private final PasswordEncoder passwordEncoder;
private final RefreshTokenService refreshTokenService;
@Override
@Transactional
public AuthResponse login(AdminLoginRequest loginRequest) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
Authentication auth = authenticationManager.authenticate(authToken);
SecurityContextHolder.getContext().setAuthentication(auth);
JwtUserDetails userDetails = (JwtUserDetails) auth.getPrincipal();
String accessToken = jwtTokenProvider.generateJwtToken(auth);
List<String> roles = userDetails.getAuthorities().stream().map(item -> item.getAuthority())
.collect(Collectors.toList());
RefreshToken refreshToken = refreshTokenService.createRefreshToken(userDetails.getId());
Date expiryDate = new Date(new Date().getTime() + EXPIRES_IN);
return AuthResponse.builder()
.username(userDetails.getUsername())
.accessToken("Bearer " + accessToken)
.roles(roles)
.refreshToken(refreshToken.getToken())
.message("success")
.expireDate(expiryDate.getTime())
.build();
}
下面是AuthServiceTest
@ExtendWith(MockitoExtension.class)
class AuthServiceTest{
@Mock
private UserRepository userRepository;
@Mock
private OrganizationRepository organizationRepository;
@InjectMocks
private AuthServiceImpl authService;
@Mock
private PasswordEncoder passwordEncoder;
@Mock
private UserMapper userMapper;
@Mock
private RefreshTokenService refreshTokenService;
@Mock
private JwtTokenProvider jwtTokenProvider;
@Mock
private AuthenticationManager authenticationManager;
@Test
void shouldLogin() {
// Given
AdminLoginRequest loginRequest = getLoginRequest();
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
Authentication auth = authenticationManager.authenticate(authToken);
SecurityContextHolder.getContext().setAuthentication(auth);
JwtUserDetails userDetails = (JwtUserDetails) auth.getPrincipal();
AuthResponse authResponse = AuthResponse.builder()
.expireDate(new Date().getTime() + 120000)
.refreshToken("refreshToken")
.message("success")
.accessToken("Bearer access-token")
.roles(List.of("ADMIN","SUPER_ADMIN"))
.username("adminUsername")
.build();
RefreshToken refreshToken = RefreshToken.builder()
.token(authResponse.getAccessToken())
.build();
// when
when(authenticationManager.authenticate(any())).thenReturn(authToken);
when(jwtTokenProvider.generateJwtToken(any())).thenReturn(authResponse.getAccessToken());
when(refreshTokenService.createRefreshToken(eq(userDetails.getId()))).thenReturn(refreshToken);
AuthResponse authResponseActual = authService.login(loginRequest);
// then
assertThat(authResponse).isNotNull();
assertEquals(authResponseActual.getAccessToken(), authResponse.getAccessToken());
assertEquals(authResponseActual.getUsername(), authResponse.getUsername());
assertEquals(authResponseActual.getRefreshToken(), authResponse.getRefreshToken());
assertEquals(authResponseActual.getRefreshToken(), authResponse.getRefreshToken());
assertEquals(authResponseActual.getMessage(), authResponse.getMessage());
}
下面是getLoginRequest
public AdminLoginRequest getLoginRequest() {
return AdminLoginRequest.builder()
.username("adminUsername")
.password("adminPassword")
.build();
}
订正
下面是测试方法
@Test
void shouldLogin() {
// Given
AdminLoginRequest loginRequest = new UserBuilder().getLoginRequest();
User user = User.builder()
.username(loginRequest.getUsername())
.password(loginRequest.getPassword())
.userRole(UserRole.ROLE_ADMIN)
.build();
user.setId(1L);
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
SecurityContextHolder.getContext().setAuthentication(auth);
AuthResponse authResponse = AuthResponse.builder()
.expireDate(new Date().getTime() + 120000)
.refreshToken("refreshToken")
.message("success")
.accessToken("Bearer access-token")
.roles(List.of("ADMIN","SUPER_ADMIN"))
.username("adminUsername")
.build();
RefreshToken refreshToken = RefreshToken.builder()
.token(authResponse.getAccessToken())
.build();
// when
when(authenticationManager.authenticate(eq(authToken))).thenReturn(authToken);
when(auth.getPrincipal()).thenReturn(jwtUserDetails);
when(jwtTokenProvider.generateJwtToken(eq(auth))).thenReturn(authResponse.getAccessToken());
when(refreshTokenService.createRefreshToken(eq(jwtUserDetails.getId()))).thenReturn(refreshToken);
AuthResponse authResponseActual = authService.login(loginRequest);
// then
assertThat(authResponse).isNotNull();
assertEquals(authResponseActual.getAccessToken(), authResponse.getAccessToken());
assertEquals(authResponseActual.getUsername(), authResponse.getUsername());
assertEquals(authResponseActual.getRefreshToken(), authResponse.getRefreshToken());
assertEquals(authResponseActual.getRefreshToken(), authResponse.getRefreshToken());
assertEquals(authResponseActual.getMessage(), authResponse.getMessage());
}
下面是问题显示
java.lang.ClassCastException: class java.lang.String cannot be cast to class com.ays.backend.user.security.JwtUserDetails (java.lang.String is in module java.base of loader 'bootstrap'; com.ays.backend.user.security.JwtUserDetails is in unnamed module of loader 'app')
2条答案
按热度按时间dsekswqp1#
JwtUserDetails jwtUserDetails:
不要忘记在测试中删除两行代码
jhdbpxl92#
下面是答案