package com.tcm.training.admin.app.settings.service;
|
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.tcm.training.admin.app.auth.service.AppAuthSessionService;
|
import com.tcm.training.admin.app.auth.service.AppSmsCodeService;
|
import com.tcm.training.admin.app.auth.service.AppWechatAuthClient;
|
import com.tcm.training.admin.app.settings.dto.AppSettingsPhoneBindRequest;
|
import com.tcm.training.admin.app.settings.mapper.AppUserNotificationSettingMapper;
|
import com.tcm.training.admin.app.settings.vo.AppSettingsProfileVO;
|
import com.tcm.training.admin.member.entity.AppUser;
|
import com.tcm.training.admin.member.mapper.UserMapper;
|
import com.tcm.training.admin.upload.ObsUploadService;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.Captor;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
/**
|
* APP 设置服务手机号绑定测试。
|
*/
|
@ExtendWith(MockitoExtension.class)
|
class AppSettingsServiceTest {
|
|
@BeforeAll
|
static void initLambdaCache() {
|
MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(), "");
|
TableInfoHelper.initTableInfo(assistant, AppUser.class);
|
}
|
|
@Mock
|
private AppAuthSessionService appAuthSessionService;
|
|
@Mock
|
private UserMapper userMapper;
|
|
@Mock
|
private AppSmsCodeService appSmsCodeService;
|
|
@Mock
|
private BCryptPasswordEncoder passwordEncoder;
|
|
@Mock
|
private AppWechatAuthClient appWechatAuthClient;
|
|
@Mock
|
private AppUserNotificationSettingMapper appUserNotificationSettingMapper;
|
|
@Mock
|
private ObsUploadService obsUploadService;
|
|
@Captor
|
private ArgumentCaptor<AppUser> appUserCaptor;
|
|
private AppSettingsService appSettingsService;
|
|
/**
|
* 每个用例前重新构造被测设置服务。
|
*/
|
@BeforeEach
|
void setUp() {
|
appSettingsService = new AppSettingsService(
|
appAuthSessionService,
|
userMapper,
|
appSmsCodeService,
|
passwordEncoder,
|
appWechatAuthClient,
|
appUserNotificationSettingMapper,
|
obsUploadService
|
);
|
}
|
|
/**
|
* 微信登录后未绑定手机号的用户,可通过验证码首次绑定手机号。
|
*/
|
@Test
|
void bindPhoneShouldUpdateCurrentUserWhenPhoneMissing() {
|
AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest();
|
request.setNewPhone("13800138000");
|
request.setCode("123456");
|
AppUser currentUser = buildEnabledUser(null);
|
|
when(appAuthSessionService.requireLoginUserId()).thenReturn(1L);
|
when(userMapper.selectById(1L)).thenReturn(currentUser);
|
when(userMapper.selectOne(any())).thenReturn(null);
|
doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456");
|
|
AppSettingsProfileVO response = appSettingsService.bindPhone(request);
|
|
verify(userMapper).updateById(appUserCaptor.capture());
|
assertEquals("13800138000", appUserCaptor.getValue().getPhone());
|
assertEquals("13800138000", response.getPhone());
|
}
|
|
/**
|
* 已绑定手机号的用户不允许走首次绑定接口。
|
*/
|
@Test
|
void bindPhoneShouldRejectWhenCurrentUserAlreadyHasPhone() {
|
AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest();
|
request.setNewPhone("13800138000");
|
request.setCode("123456");
|
|
when(appAuthSessionService.requireLoginUserId()).thenReturn(1L);
|
when(userMapper.selectById(1L)).thenReturn(buildEnabledUser("13900139000"));
|
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
() -> appSettingsService.bindPhone(request));
|
|
assertEquals("当前账号已绑定手机号", exception.getMessage());
|
verify(appSmsCodeService, never()).validatePhoneChangeCode(any(), any());
|
verify(userMapper, never()).updateById(any());
|
}
|
|
/**
|
* 目标手机号被其他有效用户占用时不允许绑定。
|
*/
|
@Test
|
void bindPhoneShouldRejectOccupiedPhone() {
|
AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest();
|
request.setNewPhone("13800138000");
|
request.setCode("123456");
|
AppUser occupiedUser = buildEnabledUser("13800138000");
|
occupiedUser.setId(2L);
|
|
when(appAuthSessionService.requireLoginUserId()).thenReturn(1L);
|
when(userMapper.selectById(1L)).thenReturn(buildEnabledUser(null));
|
when(userMapper.selectOne(any())).thenReturn(occupiedUser);
|
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
() -> appSettingsService.bindPhone(request));
|
|
assertEquals("该手机号已注册", exception.getMessage());
|
verify(appSmsCodeService, never()).validatePhoneChangeCode(any(), any());
|
verify(userMapper, never()).updateById(any());
|
}
|
|
/**
|
* 验证码错误时不应更新用户手机号。
|
*/
|
@Test
|
void bindPhoneShouldNotUpdateWhenSmsCodeInvalid() {
|
AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest();
|
request.setNewPhone("13800138000");
|
request.setCode("000000");
|
|
when(appAuthSessionService.requireLoginUserId()).thenReturn(1L);
|
when(userMapper.selectById(1L)).thenReturn(buildEnabledUser(null));
|
when(userMapper.selectOne(any())).thenReturn(null);
|
org.mockito.Mockito.doThrow(new IllegalArgumentException("验证码错误"))
|
.when(appSmsCodeService).validatePhoneChangeCode("13800138000", "000000");
|
|
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
|
() -> appSettingsService.bindPhone(request));
|
|
assertEquals("验证码错误", exception.getMessage());
|
verify(userMapper, never()).updateById(any());
|
}
|
|
/**
|
* 构造启用状态 APP 用户。
|
*/
|
private AppUser buildEnabledUser(String phone) {
|
AppUser user = new AppUser();
|
user.setId(1L);
|
user.setNickname("微信用户");
|
user.setAvatar("avatar.png");
|
user.setPhone(phone);
|
user.setType(0);
|
user.setStatus(1);
|
user.setDeleted(0);
|
return user;
|
}
|
}
|