package com.tourguide.modules.user.service; import com.tourguide.common.exception.BusinessException; import com.tourguide.modules.order.mapper.TourOrderMapper; import com.tourguide.modules.user.domain.ClientType; import com.tourguide.modules.user.entity.MiniUser; import com.tourguide.modules.user.mapper.MiniUserMapper; import com.tourguide.security.JwtTokenService; import com.tourguide.security.TokenPayload; import com.tourguide.security.TokenSessionService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class MiniAccountServiceTest { private MiniUserMapper miniUserMapper; private TourOrderMapper tourOrderMapper; private JwtTokenService jwtTokenService; private TokenSessionService tokenSessionService; private MiniAccountService accountService; private TokenPayload payload; @BeforeEach void setUp() { miniUserMapper = mock(MiniUserMapper.class); tourOrderMapper = mock(TourOrderMapper.class); jwtTokenService = mock(JwtTokenService.class); tokenSessionService = mock(TokenSessionService.class); accountService = new MiniAccountService( miniUserMapper, tourOrderMapper, jwtTokenService, tokenSessionService); payload = new TokenPayload(1L, "wx_user", "MINI_USER", ClientType.MINI, "token-id"); when(jwtTokenService.parse("mini-token")).thenReturn(payload); } @Test void shouldRejectCancellationWhenActiveOrderExists() { when(tourOrderMapper.selectCount(any())).thenReturn(1L); assertThatThrownBy(() -> accountService.cancel(1L, "mini-token")) .isInstanceOf(BusinessException.class) .hasMessage("存在未完成订单,暂时无法注销账号"); verify(miniUserMapper, never()).deleteById(1L); verify(tokenSessionService, never()).remove(payload); } @Test void shouldAnonymizeAndLogicallyDeleteAccount() { MiniUser user = new MiniUser(); user.setId(1L); user.setUsername("wx_user"); user.setNickname("游客"); user.setMobile("13800138000"); user.setAvatar("/avatar.png"); user.setRealName("张三"); user.setIdCardNo("11010519491231002X"); user.setOpenid("openid-1"); user.setStatus(1); when(tourOrderMapper.selectCount(any())).thenReturn(0L); when(miniUserMapper.selectById(1L)).thenReturn(user); accountService.cancel(1L, "mini-token"); ArgumentCaptor userCaptor = ArgumentCaptor.forClass(MiniUser.class); verify(miniUserMapper).updateById(userCaptor.capture()); MiniUser anonymized = userCaptor.getValue(); assertThat(anonymized.getUsername()).startsWith("deleted_").hasSize(32); assertThat(anonymized.getNickname()).isEqualTo("已注销用户"); assertThat(anonymized.getMobile()).isNull(); assertThat(anonymized.getAvatar()).isNull(); assertThat(anonymized.getRealName()).isNull(); assertThat(anonymized.getIdCardNo()).isNull(); assertThat(anonymized.getOpenid()).isNull(); assertThat(anonymized.getStatus()).isZero(); verify(miniUserMapper).deleteById(1L); verify(tokenSessionService).remove(payload); } }