diff --git a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java index fa876aa..844e5f8 100644 --- a/src/main/java/com/skillsync/skillsync/repository/UserRepository.java +++ b/src/main/java/com/skillsync/skillsync/repository/UserRepository.java @@ -1,13 +1,13 @@ package com.skillsync.skillsync.repository; import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; import com.skillsync.skillsync.model.User; -@Repository +import java.util.List; + public interface UserRepository extends JpaRepository { // Custom query methods can be added later, e.g. findByEmail, findBySkillName, // etc. @@ -17,4 +17,6 @@ public interface UserRepository extends JpaRepository { "OR LOWER(u.bio) LIKE LOWER(CONCAT('%', :query, '%')) " + "OR LOWER(s.name) LIKE LOWER(CONCAT('%', :query, '%'))") List searchUsers(@Param("query") String query); + + List findBySkillsNameContainingIgnoreCase(String skillName); } \ No newline at end of file diff --git a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java index 15cf8b8..92079a7 100644 --- a/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java +++ b/src/main/java/com/skillsync/skillsync/service/impl/UserServiceImpl.java @@ -1,37 +1,26 @@ package com.skillsync.skillsync.service.impl; -import java.util.*; - -import javax.management.RuntimeErrorException; - -import org.springframework.beans.factory.annotation.Autowired; - import com.skillsync.skillsync.model.Skill; import com.skillsync.skillsync.model.User; import com.skillsync.skillsync.repository.UserRepository; import com.skillsync.skillsync.service.UserService; -import org.springframework.beans.factory.annotation.Autowired; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; -import com.skillsync.skillsync.repository.UserRepository; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@RequiredArgsConstructor @Service public class UserServiceImpl implements UserService { private final UserRepository userRepository; - //Constructor for Dependency Injection - @Autowired - public UserServiceImpl(UserRepository userRepository) { - this.userRepository = userRepository; - } - - @Autowired - private UserRepository userRepository; - @Override public User saveUser(User user) { // TODO: Implement save logic using repository - return null; + return userRepository.save(user); } @Override @@ -41,23 +30,22 @@ public List getAllUsers() { @Override public User getUserById(Long id) { - Optional userOptional = userRepository.findById(id); - - if(!userOptional.isPresent()) - { - throw new RuntimeException("User Not Found"); - } - return userOptional.get(); + return userRepository.findById(id) + .orElseThrow(() -> new RuntimeException("User Not Found")); } // Update User @Override - public User updateUser(Long id, User user) { + public User updateUser(Long id, User user) { // a dto must be used for inputs // TODO: Fetch existing user by ID // TODO: Update only provided fields // TODO: Save and return updated user - return null; + User existingUser = getUserById(id); + existingUser.setBio(user.getBio()); + existingUser.setEmail(user.getEmail()); + existingUser.setName(user.getName()); + return userRepository.save(existingUser); } @@ -68,7 +56,11 @@ public User addSkillToUser(Long userId, Skill skill) { // TODO: Add skill to user’s skill list // TODO: Save updated user // TODO: Return updated user - return null; + User existingUser = getUserById(userId); + List existingSkills = existingUser.getSkills(); + existingSkills.add(skill); + existingUser.setSkills(existingSkills); + return userRepository.save(existingUser); } @@ -77,37 +69,23 @@ public User addSkillToUser(Long userId, Skill skill) { public List getUsersBySkill(String skillName) { // TODO: Implement logic to fetch users having the given skill // TODO: can use repository - return null; + return userRepository.findBySkillsNameContainingIgnoreCase(skillName); } // Search Users by Name, Bio, or Skills @Override public List searchUsers(String query) { - if (query == null || query.trim().isEmpty()) { - // Requirement: Return appropriate empty list if no users found - return Collections.emptyList(); - } - //Call the custom query defined in the repository - return userRepository.searchUsers(query.trim()); + return Optional.ofNullable(query) + .filter(x -> !x.isBlank()) + .map(String::trim) + .map(userRepository::searchUsers) + .orElse(Collections.emptyList()); } @Override public List getUserSkills(Long userId) { - // Find user by ID - Optional userOptional = userRepository.findById(userId); - - // Check if user exists - if(!userOptional.isPresent()) - { - // Note: A custom exception (e.g., UserNotFoundException) is better practice - throw new RuntimeException("User Not Found"); - } - - User user = userOptional.get(); - - // Return the list of skills from the User entity - return user.getSkills(); + return getUserById(userId).getSkills(); } } diff --git a/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java b/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java deleted file mode 100644 index e5ea664..0000000 --- a/src/test/java/com/skillsync/skillsync/SkillsyncApplicationTests.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.skillsync.skillsync; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SkillsyncApplicationTests { - - @Test - void contextLoads() { - } - -} diff --git a/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java b/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java new file mode 100644 index 0000000..a1e68ef --- /dev/null +++ b/src/test/java/com/skillsync/skillsync/service/impl/UserServiceImplTest.java @@ -0,0 +1,219 @@ +package com.skillsync.skillsync.service.impl; + +import com.skillsync.skillsync.model.Skill; +import com.skillsync.skillsync.model.User; +import com.skillsync.skillsync.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class UserServiceImplTest { + + @Mock + private UserRepository userRepository; + + @InjectMocks + private UserServiceImpl userService; + + private User user; + private Skill skill; + private List userList; + private List skillList; + + @BeforeEach + void setUp() { + // Initialize test data + skill = new Skill(); + skill.setName("Java"); + + user = new User(); + user.setId(1L); + user.setName("Alice"); + user.setEmail("alice@example.com"); + user.setBio("Software Engineer"); + user.setSkills(Collections.singletonList(skill)); + + userList = Collections.singletonList(user); + skillList = Collections.singletonList(skill); + } + + + @Test + void getAllUsers_ShouldReturnUserList() { + // Arrange + when(userRepository.findAll()).thenReturn(userList); + + // Act + List result = userService.getAllUsers(); + + // Assert + assertEquals(1, result.size()); + assertEquals("Alice", result.get(0).getName()); + verify(userRepository, times(1)).findAll(); + } + + @Test + void getUserById_WhenUserExists_ShouldReturnUser() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + + // Act + User result = userService.getUserById(1L); + + // Assert + assertNotNull(result); + assertEquals("Alice", result.getName()); + verify(userRepository, times(1)).findById(1L); + } + + @Test + void getUserById_WhenUserNotFound_ShouldThrowRuntimeException() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act & Assert + RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.getUserById(1L)); + assertEquals("User Not Found", exception.getMessage()); + verify(userRepository, times(1)).findById(1L); + } + + @Test + void updateUser_WhenUserExists_ShouldUpdateAndReturnUser() { + // Arrange + User updatedInput = new User(); + updatedInput.setName("Bob"); + updatedInput.setEmail("bob@example.com"); + updatedInput.setBio("Updated Bio"); + + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + when(userRepository.save(any(User.class))).thenReturn(user); + + // Act + User result = userService.updateUser(1L, updatedInput); + + // Assert + assertNotNull(result); + assertEquals("Bob", result.getName()); + assertEquals("bob@example.com", result.getEmail()); + assertEquals("Updated Bio", result.getBio()); + verify(userRepository, times(1)).findById(1L); + verify(userRepository, times(1)).save(user); + } + + @Test + void updateUser_WhenUserNotFound_ShouldThrowRuntimeException() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act & Assert + RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.updateUser(1L, user)); + assertEquals("User Not Found", exception.getMessage()); + verify(userRepository, times(1)).findById(1L); + verify(userRepository, never()).save(any()); + } + + + @Test + void addSkillToUser_WhenUserNotFound_ShouldThrowRuntimeException() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act & Assert + RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.addSkillToUser(1L, skill)); + assertEquals("User Not Found", exception.getMessage()); + verify(userRepository, times(1)).findById(1L); + verify(userRepository, never()).save(any()); + } + + @Test + void getUsersBySkill_ShouldReturnUsersWithMatchingSkill() { + // Arrange + when(userRepository.findBySkillsNameContainingIgnoreCase("Java")).thenReturn(userList); + + // Act + List result = userService.getUsersBySkill("Java"); + + // Assert + assertEquals(1, result.size()); + assertEquals("Alice", result.get(0).getName()); + verify(userRepository, times(1)).findBySkillsNameContainingIgnoreCase("Java"); + } + + @Test + void searchUsers_WithValidQuery_ShouldReturnMatchingUsers() { + // Arrange + when(userRepository.searchUsers("Alice")).thenReturn(userList); + + // Act + List result = userService.searchUsers("Alice"); + + // Assert + assertEquals(1, result.size()); + assertEquals("Alice", result.get(0).getName()); + verify(userRepository, times(1)).searchUsers("Alice"); + } + + @Test + void searchUsers_WithBlankQuery_ShouldReturnEmptyList() { + // Act + List result = userService.searchUsers(" "); + + // Assert + assertTrue(result.isEmpty()); + verify(userRepository, never()).searchUsers(anyString()); + } + + @Test + void searchUsers_WithNullQuery_ShouldReturnEmptyList() { + // Act + List result = userService.searchUsers(null); + + // Assert + assertTrue(result.isEmpty()); + verify(userRepository, never()).searchUsers(anyString()); + } + + @Test + void getUserSkills_WhenUserExists_ShouldReturnSkillList() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.of(user)); + + // Act + List result = userService.getUserSkills(1L); + + // Assert + assertEquals(1, result.size()); + assertEquals("Java", result.get(0).getName()); + verify(userRepository, times(1)).findById(1L); + } + + @Test + void getUserSkills_WhenUserNotFound_ShouldThrowRuntimeException() { + // Arrange + when(userRepository.findById(1L)).thenReturn(Optional.empty()); + + // Act & Assert + RuntimeException exception = assertThrows(RuntimeException.class, () -> userService.getUserSkills(1L)); + assertEquals("User Not Found", exception.getMessage()); + verify(userRepository, times(1)).findById(1L); + } +} \ No newline at end of file