package com.tourguide.modules.user.service; import com.tourguide.modules.user.domain.ClientType; import com.tourguide.modules.system.service.AdminPermissionService; import com.tourguide.modules.user.domain.UserRole; import com.tourguide.modules.user.dto.AuthResponse; import com.tourguide.modules.user.dto.MiniUserResponse; 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 org.springframework.security.crypto.password.PasswordEncoder; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; 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 AuthServiceWechatLoginTest { private MiniUserMapper miniUserMapper; private PasswordEncoder passwordEncoder; private JwtTokenService jwtTokenService; private TokenSessionService tokenSessionService; private AuthService authService; @BeforeEach void setUp() { miniUserMapper = mock(MiniUserMapper.class); passwordEncoder = mock(PasswordEncoder.class); jwtTokenService = mock(JwtTokenService.class); tokenSessionService = mock(TokenSessionService.class); authService = new AuthService( mock(AdminUserService.class), mock(AdminPermissionService.class), mock(MiniUserService.class), mock(GuideUserService.class), mock(GuideAutoDisableService.class), miniUserMapper, passwordEncoder, jwtTokenService, tokenSessionService); when(passwordEncoder.encode(anyString())).thenReturn("encoded-password"); when(jwtTokenService.createToken(anyLong(), anyString(), eq(UserRole.MINI_USER.name()), eq(ClientType.MINI))) .thenReturn("mini-token"); when(jwtTokenService.getExpirationSeconds()).thenReturn(7200L); when(jwtTokenService.parse("mini-token")) .thenReturn(new TokenPayload(1L, "wx-user", UserRole.MINI_USER.name(), ClientType.MINI, "token-id")); } @Test void shouldCreateMiniUserOnFirstWechatLogin() { when(miniUserMapper.selectOne(any())).thenReturn(null); doAnswer(invocation -> { MiniUser user = invocation.getArgument(0); user.setId(1L); return 1; }).when(miniUserMapper).insert(any(MiniUser.class)); AuthResponse response = authService.loginMiniWechat("openid-1", "13800138000"); ArgumentCaptor userCaptor = ArgumentCaptor.forClass(MiniUser.class); verify(miniUserMapper).insert(userCaptor.capture()); MiniUser user = userCaptor.getValue(); assertThat(user.getUsername()).startsWith("wx_").hasSize(32); assertThat(user.getPassword()).isEqualTo("encoded-password"); assertThat(user.getOpenid()).isEqualTo("openid-1"); assertThat(user.getMobile()).isEqualTo("13800138000"); assertThat(response.getToken()).isEqualTo("mini-token"); assertThat(response.getUser().getId()).isEqualTo(1L); verify(tokenSessionService).save(any(TokenPayload.class), eq(7200L)); } @Test void shouldReuseExistingWechatUserAndRefreshMobile() { MiniUser user = new MiniUser(); user.setId(2L); user.setUsername("wx_existing"); user.setPassword("encoded-password"); user.setNickname("微信用户"); user.setMobile("13900139000"); user.setOpenid("openid-2"); user.setStatus(1); when(miniUserMapper.selectOne(any())).thenReturn(user); AuthResponse response = authService.loginMiniWechat("openid-2", "13800138000"); verify(miniUserMapper, never()).insert(any(MiniUser.class)); verify(miniUserMapper).updateById(user); assertThat(response.getUser().getId()).isEqualTo(2L); assertThat(response.getUser().getMobile()).isEqualTo("13800138000"); } }