diff --git a/src/test/java/com/linkurlshorter/urlshortener/user/UserControllerTest.java b/src/test/java/com/linkurlshorter/urlshortener/user/UserControllerTest.java index 15e64a2..46132c6 100644 --- a/src/test/java/com/linkurlshorter/urlshortener/user/UserControllerTest.java +++ b/src/test/java/com/linkurlshorter/urlshortener/user/UserControllerTest.java @@ -1,28 +1,31 @@ package com.linkurlshorter.urlshortener.user; import com.fasterxml.jackson.databind.ObjectMapper; -import com.linkurlshorter.urlshortener.auth.AuthController; -import com.linkurlshorter.urlshortener.auth.dto.AuthRequest; +import com.linkurlshorter.urlshortener.jwt.JwtUtil; +import com.linkurlshorter.urlshortener.security.CustomUserDetailsService; +import com.linkurlshorter.urlshortener.security.SecurityUserDetails; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; +import org.springframework.test.web.servlet.ResultActions; +import java.util.UUID; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.BDDMockito.given; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; /** * Unit tests for {@link UserController} class. @@ -30,40 +33,55 @@ * @author Anastasiia Usenko */ @SpringBootTest -@AutoConfigureMockMvc(addFilters = false) -@Testcontainers +@AutoConfigureMockMvc @ExtendWith(MockitoExtension.class) class UserControllerTest { - @Container - @ServiceConnection - static PostgreSQLContainer container = new PostgreSQLContainer<>("postgres:16.0-alpine"); - @Autowired private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; - @Autowired - private AuthController authController; - private AuthRequest authRequest; - private Authentication authentication; + @MockBean + private UserService userService; + + @MockBean + private JwtUtil jwtUtil; + + @MockBean + private CustomUserDetailsService customUserDetailsService; + + private User user; + + /** + * Set up method to initialize test data before each test method. + */ + @BeforeEach + void setUp() { + user = User.builder() + .id(UUID.fromString("84991c79-f6a9-4b7b-b1b4-0d66c0b92c81")) + .email("test1@gmail.com") + .password("Password1") + .role(UserRole.USER) + .build(); + } /** * Test case for the {@link UserController#changePassword(ChangeUserPasswordRequest)} method. */ @Test - void changePasswordTest() throws Exception { + @WithMockUser + void testChangePassword() throws Exception { + given(jwtUtil.getEmailFromToken(any(String.class))).willReturn(user.getEmail()); + given(userService.updateByEmailDynamically(any(User.class), any(String.class))).willReturn(1); + ChangeUserPasswordRequest request = new ChangeUserPasswordRequest("newPassword1"); - authRequest = new AuthRequest("test@email.com", "Password1"); - authentication = new UsernamePasswordAuthenticationToken(authRequest.getEmail(), authRequest.getPassword()); - SecurityContextHolder.getContext().setAuthentication(authentication); - authController.register(authRequest); - mockMvc.perform(post("/api/V1/user/change-password") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isOk()) + ResultActions resultActions = mockMvc.perform(post("/api/V1/user/change-password") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + resultActions.andExpect(status().isOk()) .andExpect(jsonPath("$.error").value("ok")); } @@ -72,44 +90,53 @@ void changePasswordTest() throws Exception { * provided email is not found. */ @Test + @WithMockUser void changePasswordFailedTest() throws Exception { ChangeUserPasswordRequest request = new ChangeUserPasswordRequest("newPassword1"); - authentication = new UsernamePasswordAuthenticationToken("failed@email.com", "PAssWORD1"); - SecurityContextHolder.getContext().setAuthentication(authentication); + given(jwtUtil.getEmailFromToken(any(String.class))).willReturn("failed@email.com"); + given(userService.updateByEmailDynamically(any(User.class), any(String.class))).willReturn(0); - mockMvc.perform(post("/api/V1/user/change-password") + ResultActions resultActions = mockMvc.perform(post("/api/V1/user/change-password") .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isNotFound()); + .content(objectMapper.writeValueAsString(request))); + + resultActions.andExpect(status().isNotFound()); } /** * Test case for the {@link UserController#changeEmail(ChangeUserEmailRequest)} method. */ @Test + @WithMockUser void changeEmailTest() throws Exception { - ChangeUserEmailRequest request = new ChangeUserEmailRequest("success@email.com"); - authRequest = new AuthRequest("test1@email.com", "Password1"); - authentication = new UsernamePasswordAuthenticationToken(authRequest.getEmail(), authRequest.getPassword()); - SecurityContextHolder.getContext().setAuthentication(authentication); - authController.register(authRequest); + given(jwtUtil.getEmailFromToken(any(String.class))).willReturn(user.getEmail()); + given(userService.updateByEmailDynamically(any(User.class), anyString())).willReturn(1); - mockMvc.perform(post("/api/V1/user/change-email") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(request))) - .andExpect(status().isOk()) + ChangeUserEmailRequest request = new ChangeUserEmailRequest("newEmail@example.com"); + UserDetails userDetails = new SecurityUserDetails(user); + given(customUserDetailsService.loadUserByUsername(anyString())).willReturn(userDetails); + + ResultActions resultActions = mockMvc.perform(post("/api/V1/user/change-email") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))); + + resultActions.andExpect(status().isOk()) .andExpect(jsonPath("$.error").value("ok")); } /** - * Test case for the {@link UserController#changeEmail(ChangeUserEmailRequest)} method when the user with the + * Test case for the {@link UserController#changeEmail(ChangeUserEmailRequest)} method when the user with the * provided email is not found. */ @Test + @WithMockUser void changeEmailFailedTest() throws Exception { + given(jwtUtil.getEmailFromToken(any(String.class))).willReturn("nonExistent@email.com"); + given(userService.updateByEmailDynamically(any(User.class), anyString())).willReturn(0); + ChangeUserEmailRequest request = new ChangeUserEmailRequest("failed@email.com"); - authentication = new UsernamePasswordAuthenticationToken("user@email.com", "PAssWORD1"); - SecurityContextHolder.getContext().setAuthentication(authentication); + UserDetails userDetails = new SecurityUserDetails(user); + given(customUserDetailsService.loadUserByUsername(anyString())).willReturn(userDetails); mockMvc.perform(post("/api/V1/user/change-email") .contentType(MediaType.APPLICATION_JSON)