blob: 3f06b32e0ee0b4b3dafa04ce1f0b53c638d28a71 [file] [log] [blame]
xiukirad0a7a082025-06-05 16:28:08 +08001package com.g9.g9backend.controller;
2
3import com.fasterxml.jackson.databind.ObjectMapper;
4import com.g9.g9backend.pojo.*;
5import com.g9.g9backend.pojo.DTO.*;
6import com.g9.g9backend.service.*;
7import org.junit.jupiter.api.BeforeEach;
8import org.junit.jupiter.api.Test;
9import org.mockito.InjectMocks;
10import org.mockito.Mock;
11import org.mockito.MockitoAnnotations;
12import org.springframework.http.MediaType;
13import org.springframework.test.web.servlet.MockMvc;
14import org.springframework.test.web.servlet.setup.MockMvcBuilders;
15
16import static org.mockito.ArgumentMatchers.*;
17import static org.mockito.Mockito.when;
18import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
19import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
20
21public class UserControllerTest {
22
23 private MockMvc mockMvc;
24
25 @InjectMocks
26 private UserController userController;
27
28 @Mock
29 private UserService userService;
30
31 @Mock
32 private InvitationService invitationService;
33
34 @Mock
35 private SubscriptionService subscriptionService;
36
xiukira29f8d372025-06-06 18:07:13 +080037 @Mock
38 private SearchHistoryService searchHistoryService;
39
xiukirad0a7a082025-06-05 16:28:08 +080040 private final ObjectMapper objectMapper = new ObjectMapper();
41
42 @BeforeEach
43 public void setup() {
44 MockitoAnnotations.openMocks(this);
45 mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
46 }
47
48 // 注册
49 @Test
50 public void testRegister_success() throws Exception {
51 /*
52 注意单元测试中(使用Mockito ),当多次为同一个方法设置不同的返回值时,后面的设置会覆盖前面的设置
53 可见单元测试在执行时,本质上在跑实际接口实现,当遇到被mock模拟的方法时,会来测试代码里找对应的when...thenReturn,直接看最后一个设置,所以当测试方法时,测试代码里写的和实际接口的顺序上不是一一对应
54 而是测试代码里写B C A,实际接口代码里写A B C,当实际代码跑到A时去测试代码里从后往前找到A,而不是看测试代码里第一个是不是A若是再用的逻辑
55 所以如果写成如下形式:
56 when(userService.getOne(any())).thenReturn(null);
57 ....其他代码
58 when(userService.getOne(any())).thenReturn(new User(2, "hcy", "123", null, 0, 0, null, 0, 0, 0));
59 则下面的设置会覆盖上面的设置,导致无论什么时候调用该方法,返回的都是非空对象
60 所以应该写成如下形式:
61 when(userService.getOne(any()))
62 .thenReturn(null) // 第一次调用返回null
63 .thenReturn(new User(2, "hcy", "123", null, 0, 0, null, 0, 0, 0)); // 第二次调用返回非空对象
64 */
65
66 when(userService.getOne(any()))
67 .thenReturn(null) // 第一次调用返回null,表示用户名不是已存在的
68 .thenReturn(new User(2, "hcy", "123", null, 0, 0, null, 0, 0, 0)); // 第二次调用返回非空对象,表示获取添加后的用户信息
69 // 邀请码存在且未被使用
70 when(invitationService.getOne(any())).thenReturn(new Invitation("6RCA7Y8J", 1, 0));
71 // 添加新用户
72 when(userService.save(any())).thenReturn(true);
73 // 设置该邀请码被新添加的新用户使用
74 when(invitationService.update(any())).thenReturn(true);
75 // 获取五个新邀请码
76 when(invitationService.generateInvitationCode()).thenReturn(new String[5]);
77 // 分配给新用户邀请码
78 when(invitationService.save(any())).thenReturn(true);
79 mockMvc.perform(post("/user/register")
80 .contentType(MediaType.APPLICATION_JSON)
81 .content(objectMapper.writeValueAsString(new RegisterDTO("hcy", "123", "6RCA7Y8J"))))
82 .andExpect(status().isOk());
83 }
84
85 @Test
86 public void testRegister_userExists() throws Exception {
87 // 用户名不是已存在的
88 when(userService.getOne(any())).thenReturn(new User(2, "hcy", "123", null, 0, 0, null, 0, 0, 0));
89 mockMvc.perform(post("/user/register")
90 .contentType(MediaType.APPLICATION_JSON)
91 .content(objectMapper.writeValueAsString(new RegisterDTO("hcy", "123", "6RCA7Y8J"))))
92 .andExpect(status().is(407));
93 }
94
95 @Test
96 public void testRegister_invitationNotExist() throws Exception {
97 // 用户名不是已存在的
98 when(userService.getOne(any())).thenReturn(null);
99 // 邀请码不存在
100 when(invitationService.getOne(any())).thenReturn(null);
101 mockMvc.perform(post("/user/register")
102 .contentType(MediaType.APPLICATION_JSON)
103 .content(objectMapper.writeValueAsString(new RegisterDTO("hcy", "123", "6RCA7Y8J"))))
104 .andExpect(status().is(409));
105 }
106
107 @Test
108 public void testRegister_invitationUsed() throws Exception {
109 // 用户名不是已存在的
110 when(userService.getOne(any())).thenReturn(null);
111 // 邀请码存在但已被使用
112 when(invitationService.getOne(any())).thenReturn(new Invitation("6RCA7Y8J", 1, 2));
113 mockMvc.perform(post("/user/register")
114 .contentType(MediaType.APPLICATION_JSON)
115 .content(objectMapper.writeValueAsString(new RegisterDTO("hcy", "123", "6RCA7Y8J"))))
116 .andExpect(status().is(410));
117 }
118
119 // 登录
120 @Test
121 public void testLogin_success() throws Exception {
122 // 设置请求参数
123 User user = new User();
124 user.setUsername("hcy");
125 user.setPassword("123");
126
127 when(userService.getOne(any())).thenReturn(new User(1, "hcy", "123", null, 0, 0, null, 0, 0, 0));
128
129 mockMvc.perform(post("/user/login")
130 .contentType(MediaType.APPLICATION_JSON)
131 .content(objectMapper.writeValueAsString(user)))
132 .andExpect(status().isOk());
133 }
134
135 @Test
136 public void testLogin_userNotFound() throws Exception {
137 //设置请求参数
138 User user = new User();
139 user.setUsername("hcy");
140 user.setPassword("123");
141
142 when(userService.getOne(any())).thenReturn(null);
143
144 mockMvc.perform(post("/user/login")
145 .contentType(MediaType.APPLICATION_JSON)
146 .content(objectMapper.writeValueAsString(user)))
147 .andExpect(status().is(406));
148 }
149
150 @Test
151 public void testLogin_wrongPassword() throws Exception {
152 // 设置请求参数
153 User user = new User();
154 user.setUsername("hcy");
155 user.setPassword("wrongPassword");
156
157 when(userService.getOne(any())).thenReturn(new User(1, "hcy", "123", null, 0, 0, null, 0, 0, 0));
158
159 mockMvc.perform(post("/user/login")
160 .contentType(MediaType.APPLICATION_JSON)
161 .content(objectMapper.writeValueAsString(user)))
162 .andExpect(status().is(408));
163 }
164
165 // 关注
166 @Test
167 public void testSubscription() throws Exception {
168 when(subscriptionService.save(any())).thenReturn(true);
169
170 mockMvc.perform(post("/user/subscription")
171 .contentType(MediaType.APPLICATION_JSON)
172 .content(objectMapper.writeValueAsString(new Subscription(1, 2))))
173 .andExpect(status().isOk());
174 }
xiukira29f8d372025-06-06 18:07:13 +0800175
176 // 注销
177 @Test
178 public void testUserDelete_success() throws Exception {
179
180 when(userService.getOne(any())).thenReturn(new User(1, "hcy", "123", null, 0, 0, null, 0, 0, 0));
181
182 mockMvc.perform(delete("/user")
183 .param("userId", "1")
184 .param("password", "123"))
185 .andExpect(status().isNoContent());
186 }
187
188 @Test
189 public void testUserDelete_wrongPassword() throws Exception {
190
191 when(userService.getOne(any())).thenReturn(new User(1, "hcy", "123", null, 0, 0, null, 0, 0, 0));
192
193 mockMvc.perform(delete("/user")
194 .param("userId", "1")
195 .param("password", "wrong"))
196 .andExpect(status().is(408));
197 }
198
199 // 删除搜索历史
200 @Test
201 public void testSearchDelete() throws Exception {
202
203 when(searchHistoryService.removeById(anyInt())).thenReturn(true);
204
205 mockMvc.perform(delete("/user/search")
206 .param("searchHistoryId", "1"))
207 .andExpect(status().isNoContent());
208 }
209
210 // 取消关注
211 @Test
212 public void testSubscriptionDelete() throws Exception {
213
214 when(subscriptionService.remove(any())).thenReturn(true);
215
216 mockMvc.perform(delete("/user/subscription")
217 .param("userId", "1")
218 .param("followerId", "2"))
219 .andExpect(status().isNoContent());
220 }
xiukirad0a7a082025-06-05 16:28:08 +0800221}