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; } }