Commit 241064e7d07424892b33c2d0d840ec894123cf23
1 parent
f5bec3ee
✨ feat(im): 初始化群申请 v0.3:第四把 review(优化界面,进一步对齐微信界面)
Showing
6 changed files
with
93 additions
and
44 deletions
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/controller/admin/group/ImGroupRequestController.java
| @@ -21,8 +21,6 @@ import io.swagger.v3.oas.annotations.Parameter; | @@ -21,8 +21,6 @@ import io.swagger.v3.oas.annotations.Parameter; | ||
| 21 | import io.swagger.v3.oas.annotations.tags.Tag; | 21 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 22 | import jakarta.annotation.Resource; | 22 | import jakarta.annotation.Resource; |
| 23 | import jakarta.validation.Valid; | 23 | import jakarta.validation.Valid; |
| 24 | -import jakarta.validation.constraints.Max; | ||
| 25 | -import jakarta.validation.constraints.Min; | ||
| 26 | import jakarta.validation.constraints.NotNull; | 24 | import jakarta.validation.constraints.NotNull; |
| 27 | import jakarta.validation.constraints.Size; | 25 | import jakarta.validation.constraints.Size; |
| 28 | import org.springframework.validation.annotation.Validated; | 26 | import org.springframework.validation.annotation.Validated; |
| @@ -82,18 +80,6 @@ public class ImGroupRequestController { | @@ -82,18 +80,6 @@ public class ImGroupRequestController { | ||
| 82 | return success(true); | 80 | return success(true); |
| 83 | } | 81 | } |
| 84 | 82 | ||
| 85 | - @GetMapping("/list") | ||
| 86 | - @Operation(summary = "查询「我相关」的加群申请列表(含我主动申请、我被邀请待审);游标分页") | ||
| 87 | - public CommonResult<List<ImGroupRequestRespVO>> getGroupRequestList( | ||
| 88 | - @Parameter(description = "当前列表最旧记录的 id;首页不传") | ||
| 89 | - @RequestParam(value = "lastRequestId", required = false) Long lastRequestId, | ||
| 90 | - @Parameter(description = "单次拉取条数", required = true) | ||
| 91 | - @RequestParam("limit") @Min(1) @Max(200) Integer limit) { | ||
| 92 | - List<ImGroupRequestDO> list = groupRequestService.getGroupRequestListByUserId( | ||
| 93 | - getLoginUserId(), lastRequestId, limit); | ||
| 94 | - return success(buildVOList(list)); | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | @GetMapping("/unhandled-list") | 83 | @GetMapping("/unhandled-list") |
| 98 | @Operation(summary = "查询「我管理的所有群」下的未处理加群申请列表(不分页);前端 store 据此派生横幅红点 + Drawer 列表") | 84 | @Operation(summary = "查询「我管理的所有群」下的未处理加群申请列表(不分页);前端 store 据此派生横幅红点 + Drawer 列表") |
| 99 | public CommonResult<List<ImGroupRequestRespVO>> getUnhandledRequestList() { | 85 | public CommonResult<List<ImGroupRequestRespVO>> getUnhandledRequestList() { |
| @@ -101,6 +87,15 @@ public class ImGroupRequestController { | @@ -101,6 +87,15 @@ public class ImGroupRequestController { | ||
| 101 | return success(buildVOList(list)); | 87 | return success(buildVOList(list)); |
| 102 | } | 88 | } |
| 103 | 89 | ||
| 90 | + @GetMapping("/list-by-group") | ||
| 91 | + @Operation(summary = "查询指定群下的全部加群申请(含已处理);仅群主 / 管理员可查") | ||
| 92 | + @Parameter(name = "groupId", description = "群编号", required = true, example = "1024") | ||
| 93 | + public CommonResult<List<ImGroupRequestRespVO>> getGroupRequestListByGroupId( | ||
| 94 | + @RequestParam("groupId") @NotNull(message = "群编号不能为空") Long groupId) { | ||
| 95 | + List<ImGroupRequestDO> list = groupRequestService.getGroupRequestListByGroupId(getLoginUserId(), groupId); | ||
| 96 | + return success(buildVOList(list)); | ||
| 97 | + } | ||
| 98 | + | ||
| 104 | @GetMapping("/get") | 99 | @GetMapping("/get") |
| 105 | @Operation(summary = "按 id 单查申请记录(带越权过滤;WebSocket 通知到达后用)") | 100 | @Operation(summary = "按 id 单查申请记录(带越权过滤;WebSocket 通知到达后用)") |
| 106 | @Parameter(name = "id", description = "申请记录编号", required = true) | 101 | @Parameter(name = "id", description = "申请记录编号", required = true) |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/group/ImGroupRequestMapper.java
| @@ -25,14 +25,6 @@ public interface ImGroupRequestMapper extends BaseMapperX<ImGroupRequestDO> { | @@ -25,14 +25,6 @@ public interface ImGroupRequestMapper extends BaseMapperX<ImGroupRequestDO> { | ||
| 25 | .eq(ImGroupRequestDO::getUserId, userId)); | 25 | .eq(ImGroupRequestDO::getUserId, userId)); |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | - default List<ImGroupRequestDO> selectListByUserId(Long userId, Long lastRequestId, int limit) { | ||
| 29 | - return selectList(new LambdaQueryWrapperX<ImGroupRequestDO>() | ||
| 30 | - .eq(ImGroupRequestDO::getUserId, userId) | ||
| 31 | - .ltIfPresent(ImGroupRequestDO::getId, lastRequestId) | ||
| 32 | - .orderByDesc(ImGroupRequestDO::getId) | ||
| 33 | - .last("LIMIT " + limit)); | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | default List<ImGroupRequestDO> selectListByGroupIdsAndHandleResult(Collection<Long> groupIds, Integer handleResult) { | 28 | default List<ImGroupRequestDO> selectListByGroupIdsAndHandleResult(Collection<Long> groupIds, Integer handleResult) { |
| 37 | return selectList(new LambdaQueryWrapperX<ImGroupRequestDO>() | 29 | return selectList(new LambdaQueryWrapperX<ImGroupRequestDO>() |
| 38 | .in(ImGroupRequestDO::getGroupId, groupIds) | 30 | .in(ImGroupRequestDO::getGroupId, groupIds) |
| @@ -40,6 +32,12 @@ public interface ImGroupRequestMapper extends BaseMapperX<ImGroupRequestDO> { | @@ -40,6 +32,12 @@ public interface ImGroupRequestMapper extends BaseMapperX<ImGroupRequestDO> { | ||
| 40 | .orderByDesc(ImGroupRequestDO::getId)); | 32 | .orderByDesc(ImGroupRequestDO::getId)); |
| 41 | } | 33 | } |
| 42 | 34 | ||
| 35 | + default List<ImGroupRequestDO> selectListByGroupId(Long groupId) { | ||
| 36 | + return selectList(new LambdaQueryWrapperX<ImGroupRequestDO>() | ||
| 37 | + .eq(ImGroupRequestDO::getGroupId, groupId) | ||
| 38 | + .orderByDesc(ImGroupRequestDO::getId)); | ||
| 39 | + } | ||
| 40 | + | ||
| 43 | default int updateByIdAndHandleResult(Long id, Integer expectedHandleResult, ImGroupRequestDO updateObj) { | 41 | default int updateByIdAndHandleResult(Long id, Integer expectedHandleResult, ImGroupRequestDO updateObj) { |
| 44 | return update(updateObj, new LambdaUpdateWrapper<ImGroupRequestDO>() | 42 | return update(updateObj, new LambdaUpdateWrapper<ImGroupRequestDO>() |
| 45 | .eq(ImGroupRequestDO::getId, id).eq(ImGroupRequestDO::getHandleResult, expectedHandleResult)); | 43 | .eq(ImGroupRequestDO::getId, id).eq(ImGroupRequestDO::getHandleResult, expectedHandleResult)); |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestService.java
| @@ -54,16 +54,6 @@ public interface ImGroupRequestService { | @@ -54,16 +54,6 @@ public interface ImGroupRequestService { | ||
| 54 | void createInviteRequestList(Long groupId, Long inviterUserId, Collection<Long> invitedUserIds); | 54 | void createInviteRequestList(Long groupId, Long inviterUserId, Collection<Long> invitedUserIds); |
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | - * 拉取「我相关」加群申请列表(含我主动申请、我被邀请待审);游标分页 | ||
| 58 | - * | ||
| 59 | - * @param userId 用户编号 | ||
| 60 | - * @param lastRequestId 当前列表最旧记录的 id;首页传 null | ||
| 61 | - * @param limit 单次拉取条数 | ||
| 62 | - * @return 申请记录列表,按 id 倒序 | ||
| 63 | - */ | ||
| 64 | - List<ImGroupRequestDO> getGroupRequestListByUserId(Long userId, Long lastRequestId, Integer limit); | ||
| 65 | - | ||
| 66 | - /** | ||
| 67 | * 拉取「我管理的所有群」下的未处理申请列表 | 57 | * 拉取「我管理的所有群」下的未处理申请列表 |
| 68 | * <p> | 58 | * <p> |
| 69 | * 前端 store 据此派生:每个群的未处理总数(用于群顶部横幅红点)+ 列表内容(用于 Drawer) | 59 | * 前端 store 据此派生:每个群的未处理总数(用于群顶部横幅红点)+ 列表内容(用于 Drawer) |
| @@ -74,6 +64,17 @@ public interface ImGroupRequestService { | @@ -74,6 +64,17 @@ public interface ImGroupRequestService { | ||
| 74 | List<ImGroupRequestDO> getUnhandledRequestListByOwnerOrAdmin(Long userId); | 64 | List<ImGroupRequestDO> getUnhandledRequestListByOwnerOrAdmin(Long userId); |
| 75 | 65 | ||
| 76 | /** | 66 | /** |
| 67 | + * 拉取指定群下的全部加群申请(含已处理);仅群主 / 管理员可查 | ||
| 68 | + * <p> | ||
| 69 | + * 用于群「进群申请」子页:最新一条卡片化突出 + 历史申请按 id 倒序 | ||
| 70 | + * | ||
| 71 | + * @param userId 当前用户编号;用于校验 owner / admin 身份 | ||
| 72 | + * @param groupId 群编号 | ||
| 73 | + * @return 申请记录列表,按 id 倒序 | ||
| 74 | + */ | ||
| 75 | + List<ImGroupRequestDO> getGroupRequestListByGroupId(Long userId, Long groupId); | ||
| 76 | + | ||
| 77 | + /** | ||
| 77 | * 按 id 单查申请记录;通用读接口,越权过滤交由调用方 | 78 | * 按 id 单查申请记录;通用读接口,越权过滤交由调用方 |
| 78 | * | 79 | * |
| 79 | * @param id 申请记录编号 | 80 | * @param id 申请记录编号 |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupRequestServiceImpl.java
| @@ -246,11 +246,6 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { | @@ -246,11 +246,6 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { | ||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | @Override | 248 | @Override |
| 249 | - public List<ImGroupRequestDO> getGroupRequestListByUserId(Long userId, Long lastRequestId, Integer limit) { | ||
| 250 | - return groupRequestMapper.selectListByUserId(userId, lastRequestId, limit); | ||
| 251 | - } | ||
| 252 | - | ||
| 253 | - @Override | ||
| 254 | public List<ImGroupRequestDO> getUnhandledRequestListByOwnerOrAdmin(Long userId) { | 249 | public List<ImGroupRequestDO> getUnhandledRequestListByOwnerOrAdmin(Long userId) { |
| 255 | // 1. 找出当前用户作为 OWNER / ADMIN 的所有群 | 250 | // 1. 找出当前用户作为 OWNER / ADMIN 的所有群 |
| 256 | List<ImGroupMemberDO> myMembers = groupMemberService.getActiveGroupMemberListByUserId(userId); | 251 | List<ImGroupMemberDO> myMembers = groupMemberService.getActiveGroupMemberListByUserId(userId); |
| @@ -266,6 +261,18 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { | @@ -266,6 +261,18 @@ public class ImGroupRequestServiceImpl implements ImGroupRequestService { | ||
| 266 | } | 261 | } |
| 267 | 262 | ||
| 268 | @Override | 263 | @Override |
| 264 | + public List<ImGroupRequestDO> getGroupRequestListByGroupId(Long userId, Long groupId) { | ||
| 265 | + // 1. 校验群存在 + 当前用户是群主 / 管理员 | ||
| 266 | + groupService.validateGroupExists(groupId); | ||
| 267 | + ImGroupMemberDO operator = groupMemberService.validateMemberInGroup(groupId, userId); | ||
| 268 | + if (!ImGroupMemberRoleEnum.isOwnerOrAdmin(operator.getRole())) { | ||
| 269 | + throw exception(GROUP_REQUEST_NOT_TO_ME); | ||
| 270 | + } | ||
| 271 | + // 2. 拉取该群下全部申请(含已处理);按 id 倒序,前端首条卡片化展示 | ||
| 272 | + return groupRequestMapper.selectListByGroupId(groupId); | ||
| 273 | + } | ||
| 274 | + | ||
| 275 | + @Override | ||
| 269 | public ImGroupRequestDO getGroupRequest(Long id) { | 276 | public ImGroupRequestDO getGroupRequest(Long id) { |
| 270 | return groupRequestMapper.selectById(id); | 277 | return groupRequestMapper.selectById(id); |
| 271 | } | 278 | } |
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImpl.java
| @@ -191,9 +191,9 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -191,9 +191,9 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 191 | @Override | 191 | @Override |
| 192 | public void inviteGroupMember(Long userId, ImGroupMemberInviteReqVO inviteReqVO) { | 192 | public void inviteGroupMember(Long userId, ImGroupMemberInviteReqVO inviteReqVO) { |
| 193 | Long groupId = inviteReqVO.getGroupId(); | 193 | Long groupId = inviteReqVO.getGroupId(); |
| 194 | - // 1.1 校验群存在 + 当前用户是群成员 | 194 | + // 1.1 校验群存在 + 当前用户是群成员;同时拿到 role 供下面审批分支判断 |
| 195 | ImGroupDO group = validateGroupExists(groupId); | 195 | ImGroupDO group = validateGroupExists(groupId); |
| 196 | - groupMemberService.validateMemberInGroup(groupId, userId); | 196 | + ImGroupMemberDO operator = groupMemberService.validateMemberInGroup(groupId, userId); |
| 197 | // 1.2 排除已在群中的用户 | 197 | // 1.2 排除已在群中的用户 |
| 198 | List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByGroupId(groupId); | 198 | List<ImGroupMemberDO> activeMembers = groupMemberService.getActiveGroupMemberListByGroupId(groupId); |
| 199 | activeMembers.forEach(member -> inviteReqVO.getMemberUserIds().remove(member.getUserId())); | 199 | activeMembers.forEach(member -> inviteReqVO.getMemberUserIds().remove(member.getUserId())); |
| @@ -213,13 +213,15 @@ public class ImGroupServiceImpl implements ImGroupService { | @@ -213,13 +213,15 @@ public class ImGroupServiceImpl implements ImGroupService { | ||
| 213 | throw exception(GROUP_MEMBER_EXCEED, MAX_GROUP_MEMBER); | 213 | throw exception(GROUP_MEMBER_EXCEED, MAX_GROUP_MEMBER); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | - // 2. 情况一:群开启了审批,邀请也走审批,落 group_request 等群主 / 管理员处理 | ||
| 217 | - if (Boolean.TRUE.equals(group.getJoinApproval())) { | 216 | + // 2. 情况一:群开启审批 + 邀请人是普通成员,落 group_request 等群主 / 管理员处理 |
| 217 | + // 群主 / 管理员邀请视同已审批通过,绕过审批直接拉人进群(对齐 OpenIM / 微信) | ||
| 218 | + if (Boolean.TRUE.equals(group.getJoinApproval()) | ||
| 219 | + && !ImGroupMemberRoleEnum.isOwnerOrAdmin(operator.getRole())) { | ||
| 218 | groupRequestService.createInviteRequestList(groupId, userId, memberUserIds); | 220 | groupRequestService.createInviteRequestList(groupId, userId, memberUserIds); |
| 219 | return; | 221 | return; |
| 220 | } | 222 | } |
| 221 | 223 | ||
| 222 | - // 3. 情况二:未开审批,直进;批量添加群成员,写 addSource=INVITE / inviterUserId=操作人 留痕 | 224 | + // 3. 情况二:未开审批 / 群主 / 管理员邀请,直进;批量添加群成员,写 addSource=INVITE / inviterUserId=操作人 留痕 |
| 223 | groupMemberService.addGroupMembers(groupId, memberUserIds, | 225 | groupMemberService.addGroupMembers(groupId, memberUserIds, |
| 224 | ImGroupAddSourceEnum.INVITE.getSource(), userId); | 226 | ImGroupAddSourceEnum.INVITE.getSource(), userId); |
| 225 | 227 |
yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/service/group/ImGroupServiceImplTest.java
| @@ -301,16 +301,20 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { | @@ -301,16 +301,20 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { | ||
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | @Test | 303 | @Test |
| 304 | - public void testInviteGroupMember_approval_routesToApproval() { | 304 | + public void testInviteGroupMember_approval_normalRoutesToApproval() { |
| 305 | try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | 305 | try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { |
| 306 | springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImGroupServiceImpl.class))) | 306 | springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImGroupServiceImpl.class))) |
| 307 | .thenReturn(groupService); | 307 | .thenReturn(groupService); |
| 308 | 308 | ||
| 309 | - // 准备:joinApproval=true,开启审批;任何邀请都需审批,落 group_request | 309 | + // 准备:joinApproval=true,开启审批;普通成员邀请走审批,落 group_request |
| 310 | ImGroupDO group = ImGroupDO.builder().id(10L).ownerUserId(99L) | 310 | ImGroupDO group = ImGroupDO.builder().id(10L).ownerUserId(99L) |
| 311 | .joinApproval(true) | 311 | .joinApproval(true) |
| 312 | .status(CommonStatusEnum.ENABLE.getStatus()).build(); | 312 | .status(CommonStatusEnum.ENABLE.getStatus()).build(); |
| 313 | when(groupMapper.selectById(10L)).thenReturn(group); | 313 | when(groupMapper.selectById(10L)).thenReturn(group); |
| 314 | + when(groupMemberService.validateMemberInGroup(10L, 1L)).thenReturn( | ||
| 315 | + ImGroupMemberDO.builder().groupId(10L).userId(1L) | ||
| 316 | + .role(ImGroupMemberRoleEnum.NORMAL.getRole()) | ||
| 317 | + .status(CommonStatusEnum.ENABLE.getStatus()).build()); | ||
| 314 | when(groupMemberService.getActiveGroupMemberListByGroupId(10L)).thenReturn(List.of( | 318 | when(groupMemberService.getActiveGroupMemberListByGroupId(10L)).thenReturn(List.of( |
| 315 | ImGroupMemberDO.builder().groupId(10L).userId(99L) | 319 | ImGroupMemberDO.builder().groupId(10L).userId(99L) |
| 316 | .role(ImGroupMemberRoleEnum.OWNER.getRole()) | 320 | .role(ImGroupMemberRoleEnum.OWNER.getRole()) |
| @@ -339,6 +343,48 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { | @@ -339,6 +343,48 @@ public class ImGroupServiceImplTest extends BaseMockitoUnitTest { | ||
| 339 | } | 343 | } |
| 340 | 344 | ||
| 341 | @Test | 345 | @Test |
| 346 | + public void testInviteGroupMember_approval_ownerBypassesApproval() { | ||
| 347 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||
| 348 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImGroupServiceImpl.class))) | ||
| 349 | + .thenReturn(groupService); | ||
| 350 | + | ||
| 351 | + // 准备:joinApproval=true,但邀请人是群主;视同已审批,直进群 | ||
| 352 | + ImGroupDO group = ImGroupDO.builder().id(10L).ownerUserId(1L) | ||
| 353 | + .joinApproval(true) | ||
| 354 | + .status(CommonStatusEnum.ENABLE.getStatus()).build(); | ||
| 355 | + when(groupMapper.selectById(10L)).thenReturn(group); | ||
| 356 | + when(groupMemberService.validateMemberInGroup(10L, 1L)).thenReturn( | ||
| 357 | + ImGroupMemberDO.builder().groupId(10L).userId(1L) | ||
| 358 | + .role(ImGroupMemberRoleEnum.OWNER.getRole()) | ||
| 359 | + .status(CommonStatusEnum.ENABLE.getStatus()).build()); | ||
| 360 | + when(groupMemberService.getActiveGroupMemberListByGroupId(10L)).thenReturn(List.of( | ||
| 361 | + ImGroupMemberDO.builder().groupId(10L).userId(1L) | ||
| 362 | + .role(ImGroupMemberRoleEnum.OWNER.getRole()) | ||
| 363 | + .status(CommonStatusEnum.ENABLE.getStatus()).build())); | ||
| 364 | + | ||
| 365 | + ImGroupMemberInviteReqVO reqVO = new ImGroupMemberInviteReqVO(); | ||
| 366 | + reqVO.setGroupId(10L); | ||
| 367 | + reqVO.setMemberUserIds(new ArrayList<>(List.of(2L, 3L))); | ||
| 368 | + when(friendService.getActiveFriendList(eq(1L), anyCollection())).thenReturn(List.of( | ||
| 369 | + ImFriendDO.builder().userId(1L).friendUserId(2L) | ||
| 370 | + .status(CommonStatusEnum.ENABLE.getStatus()).build(), | ||
| 371 | + ImFriendDO.builder().userId(1L).friendUserId(3L) | ||
| 372 | + .status(CommonStatusEnum.ENABLE.getStatus()).build())); | ||
| 373 | + | ||
| 374 | + // 调用 | ||
| 375 | + groupService.inviteGroupMember(1L, reqVO); | ||
| 376 | + | ||
| 377 | + // 断言:绕过审批,直接 addGroupMembers + 推 1509;不落 group_request | ||
| 378 | + verify(groupRequestService, never()).createInviteRequestList(anyLong(), anyLong(), anyCollection()); | ||
| 379 | + verify(groupMemberService).addGroupMembers(eq(10L), anyCollection(), | ||
| 380 | + eq(ImGroupAddSourceEnum.INVITE.getSource()), eq(1L)); | ||
| 381 | + ArgumentCaptor<ImGroupMessageSendDTO> dtoCaptor = ArgumentCaptor.forClass(ImGroupMessageSendDTO.class); | ||
| 382 | + verify(groupMessageService).sendGroupMessage(eq(1L), anyCollection(), dtoCaptor.capture()); | ||
| 383 | + assertEquals(ImMessageTypeEnum.GROUP_MEMBER_INVITE.getType(), dtoCaptor.getValue().getType()); | ||
| 384 | + } | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + @Test | ||
| 342 | public void testInviteGroupMember_notFriend() { | 388 | public void testInviteGroupMember_notFriend() { |
| 343 | try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | 389 | try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { |
| 344 | springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImGroupServiceImpl.class))) | 390 | springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(ImGroupServiceImpl.class))) |