zhou zhou
昨天 6241b8acad2651564c1c668a9a54821361fbb4af
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package com.vincent.rsf.server.system.controller;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.common.R;
import com.vincent.rsf.server.common.service.RedisService;
import com.vincent.rsf.server.system.entity.Menu;
import com.vincent.rsf.server.system.service.MenuService;
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.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.test.util.ReflectionTestUtils;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
 
@ExtendWith(MockitoExtension.class)
class MenuControllerTest {
 
    private static final String MENU_TREE_CACHE_FLAG = "MENU_TREE";
    private static final String MENU_TREE_CACHE_KEY = "FULL_TREE";
 
    @Mock
    private MenuService menuService;
    @Mock
    private RedisService redisService;
 
    private MenuController menuController;
 
    @BeforeEach
    void setUp() {
        menuController = new MenuController();
        ReflectionTestUtils.setField(menuController, "menuService", menuService);
        ReflectionTestUtils.setField(menuController, "redisService", redisService);
    }
 
    @Test
    void treeReturnsCachedTreeBeforeQueryingDatabase() {
        List<Menu> cachedTree = List.of(menu(1L, 0L, "System"));
        when(redisService.get(MENU_TREE_CACHE_FLAG, MENU_TREE_CACHE_KEY)).thenReturn(cachedTree);
 
        R result = menuController.tree(new HashMap<>());
 
        assertEquals(cachedTree, result.get("data"));
        verify(menuService, never()).list(any(LambdaQueryWrapper.class));
    }
 
    @Test
    void treeLoadsFromDatabaseAndCachesFullTreeWhenCacheMissing() {
        when(redisService.get(MENU_TREE_CACHE_FLAG, MENU_TREE_CACHE_KEY)).thenReturn(null);
        when(menuService.list(any(LambdaQueryWrapper.class))).thenReturn(List.of(
                menu(1L, 0L, "System"),
                menu(2L, 1L, "User")
        ));
 
        R result = menuController.tree(new HashMap<>());
 
        List<Menu> tree = cast(result.get("data"));
        assertEquals(1, tree.size());
        assertNotNull(tree.get(0).getChildren());
        assertEquals(1, tree.get(0).getChildren().size());
 
        ArgumentCaptor<Object> captor = ArgumentCaptor.forClass(Object.class);
        verify(redisService).set(eq(MENU_TREE_CACHE_FLAG), eq(MENU_TREE_CACHE_KEY), captor.capture(), anyInt());
        List<Menu> cachedTree = cast(captor.getValue());
        assertEquals(1, cachedTree.size());
        assertEquals(1L, cachedTree.get(0).getId());
    }
 
    @Test
    void saveEvictsMenuTreeCacheAfterSuccessfulSave() {
        Menu menu = menu(1L, 0L, "System");
        when(menuService.save(menu)).thenReturn(true);
 
        menuController.save(menu);
 
        verify(redisService).delete(MENU_TREE_CACHE_FLAG, MENU_TREE_CACHE_KEY);
    }
 
    @Test
    void updateEvictsMenuTreeCacheAfterSuccessfulUpdate() {
        Menu menu = menu(1L, 0L, "System");
        when(menuService.updateById(menu)).thenReturn(true);
 
        menuController.update(menu);
 
        verify(redisService).delete(MENU_TREE_CACHE_FLAG, MENU_TREE_CACHE_KEY);
    }
 
    @Test
    void removeEvictsMenuTreeCacheAfterSuccessfulRemove() {
        when(menuService.removeByIds(List.of(1L, 2L))).thenReturn(true);
 
        menuController.remove(new Long[]{1L, 2L});
 
        verify(redisService).delete(MENU_TREE_CACHE_FLAG, MENU_TREE_CACHE_KEY);
    }
 
    private Menu menu(Long id, Long parentId, String name) {
        Menu menu = new Menu();
        menu.setId(id);
        menu.setParentId(parentId);
        menu.setName(name);
        menu.setChildren(new ArrayList<>());
        return menu;
    }
 
    @SuppressWarnings("unchecked")
    private List<Menu> cast(Object value) {
        return (List<Menu>) value;
    }
}