Commit f640b67159208a0c6827574b7002e683cb0eb9b6

Authored by YunaiV
1 parent f2136c43

🐛 fix(im):codex 评审修复 IM 单测契约

- ImPrivateMessageServiceImplTest 用 getFriendState 替换已删除的 isFriend mock;返回 ImFriendStateEnum.FRIEND / NONE
- ImFriendServiceImplTest 删 stale 测试(isFriend / addFriend / deleteFriend 二参版本均已不存在);addFriend0 测试参数补齐 null displayName / addSource 凑齐 4 参签名
- 修复后 mvn -pl yudao-module-im test-compile 通过

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/friend/ImFriendServiceImplTest.java
1 1 package cn.iocoder.yudao.module.im.service.friend;
2 2  
3   -import cn.hutool.extra.spring.SpringUtil;
4 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 4 import cn.iocoder.yudao.framework.common.exception.ServiceException;
6 5 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
... ... @@ -15,21 +14,16 @@ import org.junit.jupiter.api.Test;
15 14 import org.mockito.ArgumentCaptor;
16 15 import org.mockito.InjectMocks;
17 16 import org.mockito.Mock;
18   -import org.mockito.MockedStatic;
19 17 import org.springframework.dao.DuplicateKeyException;
20 18  
21 19 import java.time.LocalDateTime;
22 20 import java.util.List;
23 21  
24   -import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FRIEND_ADD_SELF;
25 22 import static cn.iocoder.yudao.module.im.enums.ErrorCodeConstants.FRIEND_NOT_FRIEND;
26 23 import static org.junit.jupiter.api.Assertions.*;
27 24 import static org.mockito.ArgumentMatchers.any;
28   -import static org.mockito.ArgumentMatchers.anyString;
29 25 import static org.mockito.ArgumentMatchers.eq;
30   -import static org.mockito.Mockito.mockStatic;
31 26 import static org.mockito.Mockito.never;
32   -import static org.mockito.Mockito.times;
33 27 import static org.mockito.Mockito.verify;
34 28 import static org.mockito.Mockito.when;
35 29  
... ... @@ -52,28 +46,6 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
52 46 @Mock
53 47 private ImPrivateMessageService privateMessageService;
54 48  
55   - // ========== isFriend ==========
56   -
57   - @Test
58   - public void testIsFriend_enabled() {
59   - ImFriendDO friend = ImFriendDO.builder().userId(1L).friendUserId(2L)
60   - .status(CommonStatusEnum.ENABLE.getStatus()).build();
61   - when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(friend);
62   -
63   - assertTrue(friendService.isFriend(1L, 2L));
64   - }
65   -
66   - @Test
67   - public void testIsFriend_disabledOrAbsent() {
68   - when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(null);
69   - assertFalse(friendService.isFriend(1L, 2L));
70   -
71   - ImFriendDO disabled = ImFriendDO.builder().userId(1L).friendUserId(3L)
72   - .status(CommonStatusEnum.DISABLE.getStatus()).build();
73   - when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 3L)).thenReturn(disabled);
74   - assertFalse(friendService.isFriend(1L, 3L));
75   - }
76   -
77 49 // ========== updateFriend ==========
78 50  
79 51 @Test
... ... @@ -152,36 +124,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
152 124 verify(imWebSocketService, never()).sendPrivateMessageAsync(any(Long.class), any(ImPrivateMessageDTO.class));
153 125 }
154 126  
155   - // ========== addFriend ==========
156   -
157   - @Test
158   - public void testAddFriend_self() {
159   - ServiceException exception = assertThrows(ServiceException.class,
160   - () -> friendService.addFriend(1L, 1L));
161   - assertEquals(FRIEND_ADD_SELF.getCode(), exception.getCode());
162   - }
163   -
164   - @Test
165   - public void testAddFriend_success() {
166   - try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
167   - springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImFriendServiceImpl.class)))
168   - .thenReturn(friendService);
169   -
170   - // 准备
171   - when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(null);
172   - when(imFriendMapper.selectByUserIdAndFriendUserId(2L, 1L)).thenReturn(null);
173   -
174   - // 调用
175   - friendService.addFriend(1L, 2L);
176   -
177   - // 断言:校验对方存在
178   - verify(adminUserApi).validateUser(2L);
179   - // 断言:双向插入 2 条好友关系
180   - verify(imFriendMapper, times(2)).insert(any(ImFriendDO.class));
181   - // 断言:FRIEND_ADD 单条入库(双向 WebSocket 推送由 sendPrivateMessage 内部完成,mock 下不可见)
182   - verify(privateMessageService).sendPrivateMessage(eq(1L), any());
183   - }
184   - }
  127 + // ========== addFriend0(内部方法,被 becomeFriends / silentReAddFriend 调用) ==========
185 128  
186 129 @Test
187 130 public void testAddFriend0_existingEnabledSkipsUpdate() {
... ... @@ -191,7 +134,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
191 134 when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(exists);
192 135  
193 136 // 调用
194   - friendService.addFriend0(1L, 2L);
  137 + friendService.addFriend0(1L, 2L, null, null);
195 138  
196 139 // 断言:不插入,也不更新
197 140 verify(imFriendMapper, never()).insert(any(ImFriendDO.class));
... ... @@ -206,7 +149,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
206 149 when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(exists);
207 150  
208 151 // 调用
209   - friendService.addFriend0(1L, 2L);
  152 + friendService.addFriend0(1L, 2L, null, null);
210 153  
211 154 // 断言:更新 status 为 ENABLE
212 155 ArgumentCaptor<ImFriendDO> captor = ArgumentCaptor.forClass(ImFriendDO.class);
... ... @@ -224,7 +167,7 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
224 167 .thenThrow(new DuplicateKeyException("concurrent insert"));
225 168  
226 169 // 调用:应被吞掉,不抛异常
227   - friendService.addFriend0(1L, 2L);
  170 + friendService.addFriend0(1L, 2L, null, null);
228 171  
229 172 verify(imFriendMapper).insert(any(ImFriendDO.class));
230 173 }
... ... @@ -232,28 +175,6 @@ public class ImFriendServiceImplTest extends BaseMockitoUnitTest {
232 175 // ========== deleteFriend ==========
233 176  
234 177 @Test
235   - public void testDeleteFriend_success() {
236   - try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
237   - springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImFriendServiceImpl.class)))
238   - .thenReturn(friendService);
239   -
240   - ImFriendDO friend12 = ImFriendDO.builder().id(10L).userId(1L).friendUserId(2L)
241   - .status(CommonStatusEnum.ENABLE.getStatus()).build();
242   - ImFriendDO friend21 = ImFriendDO.builder().id(11L).userId(2L).friendUserId(1L)
243   - .status(CommonStatusEnum.ENABLE.getStatus()).build();
244   - when(imFriendMapper.selectByUserIdAndFriendUserId(1L, 2L)).thenReturn(friend12);
245   - when(imFriendMapper.selectByUserIdAndFriendUserId(2L, 1L)).thenReturn(friend21);
246   -
247   - friendService.deleteFriend(1L, 2L);
248   -
249   - // 断言:双向更新为 DISABLE
250   - verify(imFriendMapper, times(2)).updateById(any(ImFriendDO.class));
251   - // 断言:仅给 userId 多端推送 FRIEND_DELETE 事件(friendUserId 不感知)
252   - verify(imWebSocketService).sendPrivateMessageAsync(eq(1L), any(ImPrivateMessageDTO.class));
253   - }
254   - }
255   -
256   - @Test
257 178 public void testDeleteFriend0_alreadyDisabled() {
258 179 // 准备:已经是 DISABLE,不再更新
259 180 ImFriendDO exists = ImFriendDO.builder().id(10L).userId(1L).friendUserId(2L)
... ...
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/message/ImPrivateMessageServiceImplTest.java
... ... @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivate
6 6 import cn.iocoder.yudao.module.im.controller.admin.message.vo.privates.ImPrivateMessageSendReqVO;
7 7 import cn.iocoder.yudao.module.im.dal.dataobject.message.ImPrivateMessageDO;
8 8 import cn.iocoder.yudao.module.im.dal.mysql.message.ImPrivateMessageMapper;
  9 +import cn.iocoder.yudao.module.im.enums.friend.ImFriendStateEnum;
9 10 import cn.iocoder.yudao.module.im.enums.message.ImMessageStatusEnum;
10 11 import cn.iocoder.yudao.module.im.enums.message.ImMessageTypeEnum;
11 12 import cn.iocoder.yudao.module.im.service.friend.ImFriendService;
... ... @@ -63,7 +64,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
63 64 ImPrivateMessageSendReqVO reqVO = buildSendReqVO();
64 65 when(privateMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-001"))
65 66 .thenReturn(null);
66   - when(friendService.isFriend(1L, 2L)).thenReturn(true);
  67 + when(friendService.getFriendState(1L, 2L)).thenReturn(ImFriendStateEnum.FRIEND);
67 68 when(privateMessageMapper.insert(any(ImPrivateMessageDO.class))).thenAnswer(invocation -> {
68 69 ImPrivateMessageDO msg = invocation.getArgument(0);
69 70 msg.setId(99L);
... ... @@ -82,7 +83,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
82 83 assertNotNull(result.getSendTime());
83 84  
84 85 // 验证调用
85   - verify(friendService).isFriend(1L, 2L);
  86 + verify(friendService).getFriendState(1L, 2L);
86 87 verify(sensitiveWordService).validateText(reqVO.getContent());
87 88 verify(privateMessageMapper).insert(any(ImPrivateMessageDO.class));
88 89 // 验证推送给接收方和发送方
... ... @@ -116,7 +117,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
116 117 ImPrivateMessageSendReqVO reqVO = buildSendReqVO();
117 118 when(privateMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-001"))
118 119 .thenReturn(null);
119   - when(friendService.isFriend(1L, 2L)).thenReturn(false);
  120 + when(friendService.getFriendState(1L, 2L)).thenReturn(ImFriendStateEnum.NONE);
120 121  
121 122 // 调用并断言
122 123 ServiceException exception = assertThrows(ServiceException.class,
... ... @@ -279,7 +280,7 @@ public class ImPrivateMessageServiceImplTest extends BaseMockitoUnitTest {
279 280 ImPrivateMessageSendReqVO reqVO = buildSendReqVO();
280 281 when(privateMessageMapper.selectBySenderIdAndClientMessageId(1L, "test-uuid-001"))
281 282 .thenReturn(null);
282   - when(friendService.isFriend(1L, 2L)).thenReturn(true);
  283 + when(friendService.getFriendState(1L, 2L)).thenReturn(ImFriendStateEnum.FRIEND);
283 284 doThrow(new ServiceException(MESSAGE_SENSITIVE_WORD_BLOCKED))
284 285 .when(sensitiveWordService).validateText(reqVO.getContent());
285 286  
... ...