package com.timeline.user.service; import com.timeline.user.dao.ReactionMapper; import com.timeline.user.dao.UserMapper; import com.timeline.user.entity.Reaction; import com.timeline.user.entity.User; import com.timeline.user.service.impl.ReactionServiceImpl; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; /** * Reaction Service Unit Tests */ class ReactionServiceTest { @Mock private ReactionMapper reactionMapper; @Mock private UserMapper userMapper; @InjectMocks private ReactionServiceImpl reactionService; @BeforeEach void setUp() { MockitoAnnotations.openMocks(this); } @Test void testGetReactionSummary_Success() { // Arrange String entityType = "STORY_ITEM"; String entityId = "story123"; String currentUserId = "user1"; List reactions = new ArrayList<>(); Reaction reaction1 = new Reaction(); reaction1.setEntityType(entityType); reaction1.setEntityId(entityId); reaction1.setUserId("user1"); reaction1.setReactionType("LIKE"); reactions.add(reaction1); Reaction reaction2 = new Reaction(); reaction2.setEntityType(entityType); reaction2.setEntityId(entityId); reaction2.setUserId("user2"); reaction2.setReactionType("LOVE"); reactions.add(reaction2); when(reactionMapper.findByEntity(entityType, entityId)).thenReturn(reactions); when(reactionMapper.findByEntityAndUser(entityType, entityId, currentUserId)).thenReturn(reaction1); User user1 = new User(); user1.setUserId("user1"); user1.setUsername("User One"); when(userMapper.selectByUserId("user1")).thenReturn(user1); User user2 = new User(); user2.setUserId("user2"); user2.setUsername("User Two"); when(userMapper.selectByUserId("user2")).thenReturn(user2); // Act Map summary = reactionService.getReactionSummary(entityType, entityId, currentUserId); // Assert assertNotNull(summary); assertEquals(entityType, summary.get("entityType")); assertEquals(entityId, summary.get("entityId")); assertEquals("LIKE", summary.get("userReaction")); @SuppressWarnings("unchecked") Map counts = (Map) summary.get("counts"); assertEquals(1, counts.get("LIKE")); assertEquals(1, counts.get("LOVE")); assertEquals(0, counts.get("LAUGH")); } @Test void testAddOrUpdateReaction_NewReaction() { // Arrange String userId = "user1"; String entityType = "PHOTO"; String entityId = "photo123"; String reactionType = "LOVE"; when(reactionMapper.findByEntityAndUser(entityType, entityId, userId)).thenReturn(null); when(reactionMapper.insert(any(Reaction.class))).thenReturn(1); // Act reactionService.addOrUpdateReaction(userId, entityType, entityId, reactionType); // Assert verify(reactionMapper, times(1)).insert(any(Reaction.class)); verify(reactionMapper, never()).updateReactionType(anyString(), anyString(), anyString(), anyString()); } @Test void testAddOrUpdateReaction_UpdateExisting() { // Arrange String userId = "user1"; String entityType = "STORY_ITEM"; String entityId = "story123"; String newReactionType = "WOW"; Reaction existingReaction = new Reaction(); existingReaction.setEntityType(entityType); existingReaction.setEntityId(entityId); existingReaction.setUserId(userId); existingReaction.setReactionType("LIKE"); when(reactionMapper.findByEntityAndUser(entityType, entityId, userId)).thenReturn(existingReaction); when(reactionMapper.updateReactionType(entityType, entityId, userId, newReactionType)).thenReturn(1); // Act reactionService.addOrUpdateReaction(userId, entityType, entityId, newReactionType); // Assert verify(reactionMapper, times(1)).updateReactionType(entityType, entityId, userId, newReactionType); verify(reactionMapper, never()).insert(any(Reaction.class)); } @Test void testRemoveReaction_Success() { // Arrange String userId = "user1"; String entityType = "PHOTO"; String entityId = "photo123"; when(reactionMapper.delete(entityType, entityId, userId)).thenReturn(1); // Act reactionService.removeReaction(userId, entityType, entityId); // Assert verify(reactionMapper, times(1)).delete(entityType, entityId, userId); } @Test void testAddOrUpdateReaction_InvalidEntityType() { // Arrange String userId = "user1"; String entityType = "INVALID_TYPE"; String entityId = "entity123"; String reactionType = "LIKE"; // Act & Assert assertThrows(IllegalArgumentException.class, () -> { reactionService.addOrUpdateReaction(userId, entityType, entityId, reactionType); }); } @Test void testAddOrUpdateReaction_InvalidReactionType() { // Arrange String userId = "user1"; String entityType = "STORY_ITEM"; String entityId = "story123"; String reactionType = "INVALID_REACTION"; // Act & Assert assertThrows(IllegalArgumentException.class, () -> { reactionService.addOrUpdateReaction(userId, entityType, entityId, reactionType); }); } @Test void testGetReactionSummary_OneReactionPerUserConstraint() { // Arrange String entityType = "STORY_ITEM"; String entityId = "story123"; String userId = "user1"; // User has one reaction List reactions = new ArrayList<>(); Reaction reaction = new Reaction(); reaction.setEntityType(entityType); reaction.setEntityId(entityId); reaction.setUserId(userId); reaction.setReactionType("LIKE"); reactions.add(reaction); when(reactionMapper.findByEntity(entityType, entityId)).thenReturn(reactions); when(reactionMapper.findByEntityAndUser(entityType, entityId, userId)).thenReturn(reaction); User user = new User(); user.setUserId(userId); user.setUsername("Test User"); when(userMapper.selectByUserId(userId)).thenReturn(user); // Act Map summary = reactionService.getReactionSummary(entityType, entityId, userId); // Assert assertEquals("LIKE", summary.get("userReaction")); @SuppressWarnings("unchecked") List> recentReactions = (List>) summary.get("recentReactions"); // Verify only one reaction per user long userReactionCount = reactions.stream() .filter(r -> r.getUserId().equals(userId)) .count(); assertEquals(1, userReactionCount); } }