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,251 @@
|
||||
package com.timeline.user.service;
|
||||
|
||||
import com.timeline.user.dao.PreferencesMapper;
|
||||
import com.timeline.user.entity.UserPreferences;
|
||||
import com.timeline.user.service.impl.PreferencesServiceImpl;
|
||||
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 static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* 用户偏好设置服务测试
|
||||
* User Preferences Service Test
|
||||
*
|
||||
* Tests for Requirements 7.5, 7.6 (Theme Customization backend)
|
||||
*/
|
||||
public class PreferencesServiceTest {
|
||||
|
||||
@Mock
|
||||
private PreferencesMapper preferencesMapper;
|
||||
|
||||
@InjectMocks
|
||||
private PreferencesServiceImpl preferencesService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUserPreferences_CreatesDefaultWhenNotExists() {
|
||||
// Given: 新用户ID
|
||||
String userId = "test-user-123";
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(null);
|
||||
when(preferencesMapper.insert(any(UserPreferences.class))).thenReturn(1);
|
||||
|
||||
// When: 获取用户偏好设置
|
||||
UserPreferences preferences = preferencesService.getUserPreferences(userId);
|
||||
|
||||
// Then: 应该返回默认设置
|
||||
assertNotNull(preferences, "Preferences should not be null");
|
||||
assertEquals(userId, preferences.getUserId(), "User ID should match");
|
||||
assertEquals("auto", preferences.getThemeMode(), "Default theme mode should be auto");
|
||||
assertEquals("default", preferences.getColorScheme(), "Default color scheme should be default");
|
||||
assertEquals("grid", preferences.getGalleryLayout(), "Default gallery layout should be grid");
|
||||
assertEquals("grid", preferences.getTimelineLayout(), "Default timeline layout should be grid");
|
||||
assertEquals("grid", preferences.getAlbumLayout(), "Default album layout should be grid");
|
||||
assertEquals("medium", preferences.getCardSize(), "Default card size should be medium");
|
||||
assertEquals("chronological", preferences.getTimelineDisplayMode(), "Default timeline display mode should be chronological");
|
||||
|
||||
verify(preferencesMapper, times(1)).findByUserId(userId);
|
||||
verify(preferencesMapper, times(1)).insert(any(UserPreferences.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateThemePreferences_Light() {
|
||||
// Given: 用户ID和主题设置
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateTheme(userId, "light", "blue")).thenReturn(1);
|
||||
|
||||
// When: 更新为浅色主题
|
||||
preferencesService.updateThemePreferences(userId, "light", "blue");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateTheme(userId, "light", "blue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateThemePreferences_Dark() {
|
||||
// Given: 用户ID和主题设置
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateTheme(userId, "dark", "purple")).thenReturn(1);
|
||||
|
||||
// When: 更新为深色主题
|
||||
preferencesService.updateThemePreferences(userId, "dark", "purple");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateTheme(userId, "dark", "purple");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateThemePreferences_Auto() {
|
||||
// Given: 用户ID和主题设置
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateTheme(userId, "auto", "default")).thenReturn(1);
|
||||
|
||||
// When: 更新为自动主题
|
||||
preferencesService.updateThemePreferences(userId, "auto", "default");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateTheme(userId, "auto", "default");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateThemePreferences_InvalidThemeMode() {
|
||||
// Given: 用户ID和无效的主题模式
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
|
||||
// When & Then: 应该抛出异常
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
preferencesService.updateThemePreferences(userId, "invalid", "default");
|
||||
}, "Should throw exception for invalid theme mode");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLayoutPreferences() {
|
||||
// Given: 用户ID和布局设置
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateLayout(userId, "list", "grid", "list", "large")).thenReturn(1);
|
||||
|
||||
// When: 更新布局偏好
|
||||
preferencesService.updateLayoutPreferences(userId, "list", "grid", "list", "large");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateLayout(userId, "list", "grid", "list", "large");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLayoutPreferences_PartialUpdate() {
|
||||
// Given: 用户ID和部分布局设置
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateLayout(userId, "list", "grid", "grid", "small")).thenReturn(1);
|
||||
|
||||
// When: 只更新部分布局偏好
|
||||
preferencesService.updateLayoutPreferences(userId, "list", null, null, "small");
|
||||
|
||||
// Then: 应该使用现有值填充null字段
|
||||
verify(preferencesMapper, times(1)).updateLayout(userId, "list", "grid", "grid", "small");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLayoutPreferences_InvalidLayout() {
|
||||
// Given: 用户ID和无效的布局
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
|
||||
// When & Then: 应该抛出异常
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
preferencesService.updateLayoutPreferences(userId, "invalid", null, null, null);
|
||||
}, "Should throw exception for invalid layout");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLayoutPreferences_InvalidCardSize() {
|
||||
// Given: 用户ID和无效的卡片大小
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
|
||||
// When & Then: 应该抛出异常
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
preferencesService.updateLayoutPreferences(userId, null, null, null, "invalid");
|
||||
}, "Should throw exception for invalid card size");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateTimelineDisplayPreferences() {
|
||||
// Given: 用户ID和时间线显示模式
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateTimelineDisplay(userId, "grouped")).thenReturn(1);
|
||||
|
||||
// When: 更新时间线显示偏好
|
||||
preferencesService.updateTimelineDisplayPreferences(userId, "grouped");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateTimelineDisplay(userId, "grouped");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateTimelineDisplayPreferences_Masonry() {
|
||||
// Given: 用户ID和时间线显示模式
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
when(preferencesMapper.updateTimelineDisplay(userId, "masonry")).thenReturn(1);
|
||||
|
||||
// When: 更新为瀑布流显示
|
||||
preferencesService.updateTimelineDisplayPreferences(userId, "masonry");
|
||||
|
||||
// Then: 应该调用更新方法
|
||||
verify(preferencesMapper, times(1)).updateTimelineDisplay(userId, "masonry");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateTimelineDisplayPreferences_InvalidMode() {
|
||||
// Given: 用户ID和无效的显示模式
|
||||
String userId = "test-user-123";
|
||||
UserPreferences existing = createDefaultPreferences(userId);
|
||||
when(preferencesMapper.findByUserId(userId)).thenReturn(existing);
|
||||
|
||||
// When & Then: 应该抛出异常
|
||||
assertThrows(IllegalArgumentException.class, () -> {
|
||||
preferencesService.updateTimelineDisplayPreferences(userId, "invalid");
|
||||
}, "Should throw exception for invalid display mode");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateDefaultPreferences() {
|
||||
// Given: 新用户ID
|
||||
String userId = "test-user-123";
|
||||
when(preferencesMapper.insert(any(UserPreferences.class))).thenReturn(1);
|
||||
|
||||
// When: 创建默认偏好设置
|
||||
UserPreferences preferences = preferencesService.createDefaultPreferences(userId);
|
||||
|
||||
// Then: 应该创建包含所有默认值的偏好设置
|
||||
assertNotNull(preferences, "Preferences should not be null");
|
||||
assertEquals(userId, preferences.getUserId(), "User ID should match");
|
||||
assertEquals("auto", preferences.getThemeMode(), "Default theme mode should be auto");
|
||||
assertEquals("default", preferences.getColorScheme(), "Default color scheme should be default");
|
||||
assertEquals("grid", preferences.getGalleryLayout(), "Default gallery layout should be grid");
|
||||
assertEquals("medium", preferences.getCardSize(), "Default card size should be medium");
|
||||
assertEquals("chronological", preferences.getTimelineDisplayMode(), "Default timeline display mode should be chronological");
|
||||
|
||||
verify(preferencesMapper, times(1)).insert(any(UserPreferences.class));
|
||||
}
|
||||
|
||||
// Helper method to create default preferences for testing
|
||||
private UserPreferences createDefaultPreferences(String userId) {
|
||||
UserPreferences preferences = new UserPreferences();
|
||||
preferences.setUserId(userId);
|
||||
preferences.setThemeMode("auto");
|
||||
preferences.setColorScheme("default");
|
||||
preferences.setGalleryLayout("grid");
|
||||
preferences.setTimelineLayout("grid");
|
||||
preferences.setAlbumLayout("grid");
|
||||
preferences.setCardSize("medium");
|
||||
preferences.setTimelineDisplayMode("chronological");
|
||||
return preferences;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user