feat(user-service): 实现用户服务核心功能与数据同步
Some checks failed
test/timeline-server/pipeline/head There was a failure building this commit
Some checks failed
test/timeline-server/pipeline/head There was a failure building this commit
- 新增用户资料、偏好设置、自定义字段管理功能 - 实现评论、反应、相册与智能集合的完整业务逻辑 - 添加离线变更记录与数据同步机制支持冲突解决 - 集成 Redis 缓存配置与用户统计数据聚合 - 创建 8 个业务控制器处理用户交互请求 - 新增 Feign 客户端与故事服务集成 - 补充详细的后端实现与 WebSocket 指南文档 - 更新项目依赖配置支持新增功能模块
This commit is contained in:
@@ -0,0 +1,201 @@
|
||||
package com.timeline.user.service;
|
||||
|
||||
import com.timeline.user.dao.CommentMapper;
|
||||
import com.timeline.user.dto.CommentDto;
|
||||
import com.timeline.user.dto.CommentEventDto;
|
||||
import com.timeline.user.dto.CreateCommentRequest;
|
||||
import com.timeline.user.entity.Comment;
|
||||
import com.timeline.user.entity.User;
|
||||
import com.timeline.user.service.impl.CommentServiceImpl;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* WebSocket通知测试
|
||||
* Tests for WebSocket notifications in CommentService
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CommentWebSocketTest {
|
||||
|
||||
@Mock
|
||||
private CommentMapper commentMapper;
|
||||
|
||||
@Mock
|
||||
private UserService userService;
|
||||
|
||||
@Mock
|
||||
private SimpMessagingTemplate messagingTemplate;
|
||||
|
||||
@InjectMocks
|
||||
private CommentServiceImpl commentService;
|
||||
|
||||
private User testUser;
|
||||
private Comment testComment;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
testUser = new User();
|
||||
testUser.setUserId("user123");
|
||||
testUser.setUsername("testuser");
|
||||
testUser.setNickname("Test User");
|
||||
|
||||
testComment = new Comment();
|
||||
testComment.setId(1L);
|
||||
testComment.setInstanceId("comment123");
|
||||
testComment.setEntityType("STORY");
|
||||
testComment.setEntityId("story456");
|
||||
testComment.setUserId("user123");
|
||||
testComment.setContent("Test comment");
|
||||
testComment.setCreateTime(LocalDateTime.now());
|
||||
testComment.setUpdateTime(LocalDateTime.now());
|
||||
testComment.setIsDelete(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateComment_ShouldBroadcastWebSocketEvent() {
|
||||
// Arrange
|
||||
CreateCommentRequest request = new CreateCommentRequest();
|
||||
request.setEntityType("STORY");
|
||||
request.setEntityId("story456");
|
||||
request.setContent("Test comment");
|
||||
|
||||
when(commentMapper.insert(any(Comment.class))).thenReturn(1);
|
||||
when(commentMapper.findByInstanceId(anyString())).thenReturn(testComment);
|
||||
when(userService.getUserByUserId("user123")).thenReturn(testUser);
|
||||
|
||||
// Act
|
||||
CommentDto result = commentService.createComment("user123", request);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals("Test comment", result.getContent());
|
||||
|
||||
// Verify WebSocket message was sent
|
||||
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<CommentEventDto> eventCaptor = ArgumentCaptor.forClass(CommentEventDto.class);
|
||||
|
||||
verify(messagingTemplate, times(1)).convertAndSend(
|
||||
topicCaptor.capture(),
|
||||
eventCaptor.capture()
|
||||
);
|
||||
|
||||
// Verify topic format
|
||||
String expectedTopic = "/topic/comments/STORY/story456";
|
||||
assertEquals(expectedTopic, topicCaptor.getValue());
|
||||
|
||||
// Verify event content
|
||||
CommentEventDto event = eventCaptor.getValue();
|
||||
assertEquals(CommentEventDto.CommentEventType.CREATED, event.getEventType());
|
||||
assertEquals("STORY", event.getEntityType());
|
||||
assertEquals("story456", event.getEntityId());
|
||||
assertNotNull(event.getComment());
|
||||
assertEquals("Test comment", event.getComment().getContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateComment_ShouldBroadcastWebSocketEvent() {
|
||||
// Arrange
|
||||
String updatedContent = "Updated comment";
|
||||
Comment updatedComment = new Comment();
|
||||
updatedComment.setInstanceId("comment123");
|
||||
updatedComment.setEntityType("STORY");
|
||||
updatedComment.setEntityId("story456");
|
||||
updatedComment.setUserId("user123");
|
||||
updatedComment.setContent(updatedContent);
|
||||
updatedComment.setCreateTime(LocalDateTime.now().minusHours(1));
|
||||
updatedComment.setUpdateTime(LocalDateTime.now());
|
||||
updatedComment.setIsDelete(0);
|
||||
|
||||
when(commentMapper.findByInstanceId("comment123")).thenReturn(testComment, updatedComment);
|
||||
when(commentMapper.updateContent("comment123", updatedContent)).thenReturn(1);
|
||||
when(userService.getUserByUserId("user123")).thenReturn(testUser);
|
||||
|
||||
// Act
|
||||
CommentDto result = commentService.updateComment("comment123", "user123", updatedContent);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
|
||||
// Verify WebSocket message was sent
|
||||
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<CommentEventDto> eventCaptor = ArgumentCaptor.forClass(CommentEventDto.class);
|
||||
|
||||
verify(messagingTemplate, times(1)).convertAndSend(
|
||||
topicCaptor.capture(),
|
||||
eventCaptor.capture()
|
||||
);
|
||||
|
||||
// Verify event
|
||||
CommentEventDto event = eventCaptor.getValue();
|
||||
assertEquals(CommentEventDto.CommentEventType.UPDATED, event.getEventType());
|
||||
assertEquals("STORY", event.getEntityType());
|
||||
assertEquals("story456", event.getEntityId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteComment_ShouldBroadcastWebSocketEvent() {
|
||||
// Arrange
|
||||
when(commentMapper.findByInstanceId("comment123")).thenReturn(testComment);
|
||||
when(commentMapper.softDelete("comment123")).thenReturn(1);
|
||||
|
||||
// Act
|
||||
commentService.deleteComment("comment123", "user123", null);
|
||||
|
||||
// Assert
|
||||
// Verify WebSocket message was sent
|
||||
ArgumentCaptor<String> topicCaptor = ArgumentCaptor.forClass(String.class);
|
||||
ArgumentCaptor<CommentEventDto> eventCaptor = ArgumentCaptor.forClass(CommentEventDto.class);
|
||||
|
||||
verify(messagingTemplate, times(1)).convertAndSend(
|
||||
topicCaptor.capture(),
|
||||
eventCaptor.capture()
|
||||
);
|
||||
|
||||
// Verify event
|
||||
CommentEventDto event = eventCaptor.getValue();
|
||||
assertEquals(CommentEventDto.CommentEventType.DELETED, event.getEventType());
|
||||
assertEquals("STORY", event.getEntityType());
|
||||
assertEquals("story456", event.getEntityId());
|
||||
assertEquals("comment123", event.getCommentId());
|
||||
assertNull(event.getComment()); // Comment data should be null for delete events
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWebSocketBroadcast_ShouldNotFailMainOperation_WhenWebSocketFails() {
|
||||
// Arrange
|
||||
CreateCommentRequest request = new CreateCommentRequest();
|
||||
request.setEntityType("STORY");
|
||||
request.setEntityId("story456");
|
||||
request.setContent("Test comment");
|
||||
|
||||
when(commentMapper.insert(any(Comment.class))).thenReturn(1);
|
||||
when(commentMapper.findByInstanceId(anyString())).thenReturn(testComment);
|
||||
when(userService.getUserByUserId("user123")).thenReturn(testUser);
|
||||
|
||||
// Simulate WebSocket failure
|
||||
doThrow(new RuntimeException("WebSocket error"))
|
||||
.when(messagingTemplate).convertAndSend(anyString(), any());
|
||||
|
||||
// Act - should not throw exception
|
||||
CommentDto result = commentService.createComment("user123", request);
|
||||
|
||||
// Assert - main operation should succeed despite WebSocket failure
|
||||
assertNotNull(result);
|
||||
assertEquals("Test comment", result.getContent());
|
||||
|
||||
// Verify the WebSocket send was attempted
|
||||
verify(messagingTemplate, times(1)).convertAndSend(anyString(), any());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user