article: https://www.baeldung.com/spring-security-method-security#3-testing-with-a-custom-userdetailsservice
For most applications, it’s common to use a custom class as authentication principal. In this case, the custom class needs to implement the org.springframework.security.core.userdetails.UserDetails interface.
In this article, we declare a CustomUser class which extends the existing implementation of UserDetails, which is org.springframework.security.core.userdetails.User:
public class CustomUser extends User {
private String nickName;
// getter and setter
}
Let’s take back the example with the @PostAuthorize annotation in section 3:
@PostAuthorize("returnObject.username == authentication.principal.nickName")
public CustomUser loadUserDetail(String username) {
return userRoleRepository.loadUserByUserName(username);
}
In this case, the method would only execute successfully if the username of the returned CustomUser is equal to the current authentication principal’s nickname.
If we wanted to test that method, we could provide an implementation of UserDetailsService which could load our CustomUser based on the username:
@Test
@WithUserDetails( value = "john", userDetailsServiceBeanName = "userDetailService")
public void whenJohn_callLoadUserDetail_thenOK() {
CustomUser user = userService.loadUserDetail("jane");
assertEquals("jane", user.getNickName());
}
Here, the @WithUserDetails annotation states that we’ll use a UserDetailsService to initialize our authenticated user. The service is referred by the userDetailsServiceBeanName property. This UserDetailsService might be a real implementation or a fake for testing purposes.
Additionally, the service will use the value of the property value as the username to load UserDetails.
Conveniently, we can also decorate with a @WithUserDetails annotation at the class level, similarly to what we did with the @WithMockUser annotation.