AuthServiceTest.java 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package com.danielbohry.authservice.service.auth;
  2. import com.danielbohry.authservice.api.dto.AuthenticationRequest;
  3. import com.danielbohry.authservice.api.dto.AuthenticationResponse;
  4. import com.danielbohry.authservice.domain.ApplicationUser;
  5. import com.danielbohry.authservice.domain.Role;
  6. import com.danielbohry.authservice.service.user.UserService;
  7. import org.junit.jupiter.api.BeforeEach;
  8. import org.junit.jupiter.api.Test;
  9. import org.mockito.Mock;
  10. import org.mockito.MockitoAnnotations;
  11. import org.springframework.security.authentication.AuthenticationManager;
  12. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  13. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  14. import org.springframework.security.core.userdetails.UserDetails;
  15. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  16. import org.springframework.security.crypto.password.PasswordEncoder;
  17. import java.time.Instant;
  18. import java.util.List;
  19. import static org.junit.jupiter.api.Assertions.*;
  20. import static org.mockito.ArgumentMatchers.any;
  21. import static org.mockito.ArgumentMatchers.anyString;
  22. import static org.mockito.Mockito.*;
  23. class AuthServiceTest {
  24. @Mock
  25. private UserService userService;
  26. @Mock
  27. private JwtService jwtService;
  28. @Mock
  29. private AuthenticationManager authenticationManager;
  30. @Mock
  31. private PasswordEncoder passwordEncoder;
  32. private AuthService authService;
  33. private ApplicationUser testUser;
  34. private Authentication testAuthentication;
  35. private AuthenticationRequest testRequest;
  36. @BeforeEach
  37. void setUp() {
  38. MockitoAnnotations.openMocks(this);
  39. authService = new AuthService(userService, jwtService, authenticationManager, passwordEncoder);
  40. testUser = ApplicationUser.builder()
  41. .id("user-id-123")
  42. .username("testuser")
  43. .password("encodedPassword")
  44. .email("[email protected]")
  45. .roles(List.of(Role.USER))
  46. .active(true)
  47. .build();
  48. testAuthentication = new Authentication(
  49. "jwt-token-123",
  50. Instant.now().plusSeconds(3600),
  51. "testuser",
  52. List.of("ROLE_USER")
  53. );
  54. testRequest = new AuthenticationRequest("testuser", "password123");
  55. }
  56. @Test
  57. void shouldLoadUserByUsername() {
  58. // given
  59. when(userService.findByUsername("testuser")).thenReturn(testUser);
  60. // when
  61. UserDetails result = authService.loadUserByUsername("testuser");
  62. // then
  63. assertNotNull(result);
  64. assertEquals("testuser", result.getUsername());
  65. assertEquals("encodedPassword", result.getPassword());
  66. assertTrue(result.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_USER")));
  67. verify(userService).findByUsername("testuser");
  68. }
  69. @Test
  70. void shouldThrowExceptionForUnknownUser() {
  71. // given
  72. when(userService.findByUsername("unknown")).thenThrow(new RuntimeException("User not found"));
  73. // when/then
  74. assertThrows(RuntimeException.class, () -> authService.loadUserByUsername("unknown"));
  75. verify(userService).findByUsername("unknown");
  76. }
  77. @Test
  78. void shouldRegisterNewUser() {
  79. // given
  80. when(passwordEncoder.encode("password123")).thenReturn("encodedPassword");
  81. when(userService.create(any(ApplicationUser.class))).thenReturn(testUser);
  82. when(jwtService.generateToken(testUser)).thenReturn(testAuthentication);
  83. // when
  84. AuthenticationResponse result = authService.register(testRequest);
  85. // then
  86. assertNotNull(result);
  87. assertEquals("user-id-123", result.getId());
  88. assertEquals("testuser", result.getUsername());
  89. assertEquals("jwt-token-123", result.getToken());
  90. assertEquals(testAuthentication.expirationDate(), result.getExpirationDate());
  91. assertEquals(List.of("ROLE_USER"), result.getRoles());
  92. verify(passwordEncoder).encode("password123");
  93. verify(userService).create(any(ApplicationUser.class));
  94. verify(jwtService).generateToken(testUser);
  95. }
  96. @Test
  97. void shouldAuthenticateValidUser() {
  98. // given
  99. when(userService.findByUsername("testuser")).thenReturn(testUser);
  100. when(jwtService.generateToken(testUser)).thenReturn(testAuthentication);
  101. // when
  102. AuthenticationResponse result = authService.authenticate(testRequest);
  103. // then
  104. assertNotNull(result);
  105. assertEquals("user-id-123", result.getId());
  106. assertEquals("testuser", result.getUsername());
  107. assertEquals("jwt-token-123", result.getToken());
  108. assertEquals(testAuthentication.expirationDate(), result.getExpirationDate());
  109. assertEquals(List.of("ROLE_USER"), result.getRoles());
  110. verify(authenticationManager).authenticate(any(UsernamePasswordAuthenticationToken.class));
  111. verify(userService).findByUsername("testuser");
  112. verify(jwtService).generateToken(testUser);
  113. }
  114. @Test
  115. void shouldFailAuthenticationWithInvalidCredentials() {
  116. // given
  117. when(authenticationManager.authenticate(any(UsernamePasswordAuthenticationToken.class)))
  118. .thenThrow(new RuntimeException("Bad credentials"));
  119. // when/then
  120. assertThrows(RuntimeException.class, () -> authService.authenticate(testRequest));
  121. verify(authenticationManager).authenticate(any(UsernamePasswordAuthenticationToken.class));
  122. verifyNoInteractions(userService);
  123. verifyNoInteractions(jwtService);
  124. }
  125. @Test
  126. void shouldChangePassword() {
  127. // given
  128. String userId = "user-id-123";
  129. String currentPassword = "oldPassword";
  130. String newPassword = "newPassword";
  131. ApplicationUser updatedUser = ApplicationUser.builder()
  132. .id(userId)
  133. .username("testuser")
  134. .password("newEncodedPassword")
  135. .email("[email protected]")
  136. .roles(List.of(Role.USER))
  137. .active(true)
  138. .build();
  139. when(userService.changePassword(userId, currentPassword, newPassword, passwordEncoder))
  140. .thenReturn(updatedUser);
  141. when(jwtService.generateToken(updatedUser)).thenReturn(testAuthentication);
  142. // when
  143. AuthenticationResponse result = authService.changePassword(userId, currentPassword, newPassword);
  144. // then
  145. assertNotNull(result);
  146. assertEquals("user-id-123", result.getId());
  147. assertEquals("testuser", result.getUsername());
  148. assertEquals("jwt-token-123", result.getToken());
  149. assertEquals(testAuthentication.expirationDate(), result.getExpirationDate());
  150. assertEquals(List.of("ROLE_USER"), result.getRoles());
  151. verify(userService).changePassword(userId, currentPassword, newPassword, passwordEncoder);
  152. verify(jwtService).generateToken(updatedUser);
  153. }
  154. @Test
  155. void shouldBuildCorrectUserAuthorities() {
  156. // given
  157. ApplicationUser multiRoleUser = ApplicationUser.builder()
  158. .id("user-id-123")
  159. .username("admin")
  160. .password("encodedPassword")
  161. .email("[email protected]")
  162. .roles(List.of(Role.ADMIN, Role.USER))
  163. .active(true)
  164. .build();
  165. when(userService.findByUsername("admin")).thenReturn(multiRoleUser);
  166. // when
  167. UserDetails result = authService.loadUserByUsername("admin");
  168. // then
  169. assertNotNull(result);
  170. assertEquals(2, result.getAuthorities().size());
  171. assertTrue(result.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN")));
  172. assertTrue(result.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_USER")));
  173. }
  174. @Test
  175. void shouldEncodePasswordDuringRegistration() {
  176. // given
  177. when(passwordEncoder.encode("plainPassword")).thenReturn("encodedPassword123");
  178. when(userService.create(any(ApplicationUser.class))).thenReturn(testUser);
  179. when(jwtService.generateToken(testUser)).thenReturn(testAuthentication);
  180. AuthenticationRequest request = new AuthenticationRequest("newuser", "plainPassword");
  181. // when
  182. authService.register(request);
  183. // then
  184. verify(passwordEncoder).encode("plainPassword");
  185. verify(userService).create(argThat(user ->
  186. "encodedPassword123".equals(user.getPassword()) &&
  187. "newuser".equals(user.getUsername())
  188. ));
  189. }
  190. @Test
  191. void shouldCreateUserWithDefaultUserRole() {
  192. // given
  193. when(passwordEncoder.encode(anyString())).thenReturn("encodedPassword");
  194. when(userService.create(any(ApplicationUser.class))).thenReturn(testUser);
  195. when(jwtService.generateToken(testUser)).thenReturn(testAuthentication);
  196. // when
  197. authService.register(testRequest);
  198. // then
  199. verify(userService).create(argThat(user -> user.getRoles() == null || user.getRoles().isEmpty()));
  200. // Note: UserService.create sets default USER role internally
  201. }
  202. @Test
  203. void shouldCallAuthenticationManagerWithCorrectCredentials() {
  204. // given
  205. when(userService.findByUsername("testuser")).thenReturn(testUser);
  206. when(jwtService.generateToken(testUser)).thenReturn(testAuthentication);
  207. // when
  208. authService.authenticate(testRequest);
  209. // then
  210. verify(authenticationManager).authenticate(argThat(auth ->
  211. auth instanceof UsernamePasswordAuthenticationToken &&
  212. "testuser".equals(auth.getName()) &&
  213. "password123".equals(auth.getCredentials())
  214. ));
  215. }
  216. }