mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 17:21:53 +08:00
code review 修改密码等的单元测试
This commit is contained in:
parent
42ce5c75fd
commit
e2b76ee0e5
@ -117,8 +117,6 @@
|
|||||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.velocity</groupId>
|
<groupId>org.apache.velocity</groupId>
|
||||||
<artifactId>velocity-engine-core</artifactId>
|
<artifactId>velocity-engine-core</artifactId>
|
||||||
|
@ -91,6 +91,7 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- TODO @宋天:junit 已经在 yudao-spring-boot-starter-test 啦,不用在引入哈 -->
|
||||||
<!--单元测试相关-->
|
<!--单元测试相关-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
|
@ -70,6 +70,7 @@ public class SysUserProfileController {
|
|||||||
@PreAuthenticated
|
@PreAuthenticated
|
||||||
public CommonResult<Boolean> updateMobile(@RequestBody @Valid MbrUserUpdateMobileReqVO reqVO) {
|
public CommonResult<Boolean> updateMobile(@RequestBody @Valid MbrUserUpdateMobileReqVO reqVO) {
|
||||||
// 校验验证码
|
// 校验验证码
|
||||||
|
// TODO @宋天:统一到 userService.updateMobile 方法里
|
||||||
smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
|
smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
|
||||||
|
|
||||||
userService.updateMobile(getLoginUserId(), reqVO);
|
userService.updateMobile(getLoginUserId(), reqVO);
|
||||||
|
@ -25,9 +25,9 @@ public class MbrUserUpdateMobileReqVO {
|
|||||||
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
|
|
||||||
@ApiModelProperty(value = "手机号",required = true,example = "15823654487")
|
@ApiModelProperty(value = "手机号",required = true,example = "15823654487")
|
||||||
@NotBlank(message = "手机号不能为空")
|
@NotBlank(message = "手机号不能为空")
|
||||||
|
// TODO @宋天:手机校验,直接使用 @Mobile 哈
|
||||||
@Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
|
@Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
|
||||||
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
|
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
|
||||||
private String mobile;
|
private String mobile;
|
||||||
|
@ -126,8 +126,10 @@ public class MbrUserServiceImpl implements MbrUserService {
|
|||||||
// 检测用户是否存在
|
// 检测用户是否存在
|
||||||
MbrUserDO userDO = checkUserExists(userId);
|
MbrUserDO userDO = checkUserExists(userId);
|
||||||
// 检测手机与验证码是否匹配
|
// 检测手机与验证码是否匹配
|
||||||
|
// TODO @宋天:修改手机的时候。应该要校验,老手机 + 老手机 code;新手机 + 新手机 code
|
||||||
sysAuthService.checkIfMobileMatchCodeAndDeleteCode(userDO.getMobile(),reqVO.getCode());
|
sysAuthService.checkIfMobileMatchCodeAndDeleteCode(userDO.getMobile(),reqVO.getCode());
|
||||||
// 更新用户手机
|
// 更新用户手机
|
||||||
|
// TODO @宋天:更新的时候,单独创建对象。直接全量更新,会可能导致属性覆盖。可以看看打印出来的 SQL 哈
|
||||||
userDO.setMobile(reqVO.getMobile());
|
userDO.setMobile(reqVO.getMobile());
|
||||||
userMapper.updateById(userDO);
|
userMapper.updateById(userDO);
|
||||||
}
|
}
|
||||||
|
@ -98,6 +98,7 @@ public class SysAuthController {
|
|||||||
@ApiOperation(value = "校验验证码是否正确")
|
@ApiOperation(value = "校验验证码是否正确")
|
||||||
@PreAuthenticated
|
@PreAuthenticated
|
||||||
public CommonResult<Boolean> checkSmsCode(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) {
|
public CommonResult<Boolean> checkSmsCode(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) {
|
||||||
|
// TODO @宋天:check 的时候,不应该使用 useSmsCode 哈,这样验证码就直接被使用了。另外,check 开头的方法,更多是校验的逻辑,不会有 update 数据的动作。这点,在方法命名上,也是要注意的
|
||||||
smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHECK_CODE_BY_SMS.getScene(),reqVO.getCode(),getClientIP());
|
smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHECK_CODE_BY_SMS.getScene(),reqVO.getCode(),getClientIP());
|
||||||
return success(true);
|
return success(true);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import lombok.Data;
|
|||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.hibernate.validator.constraints.Length;
|
import org.hibernate.validator.constraints.Length;
|
||||||
|
|
||||||
import javax.validation.constraints.NotBlank;
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import javax.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
|
|
||||||
@ -29,4 +28,5 @@ public class MbrAuthResetPasswordReqVO {
|
|||||||
@Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
|
@Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
|
||||||
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
@Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
|
||||||
private String code;
|
private String code;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -285,6 +285,7 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|||||||
MbrUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
|
MbrUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
|
||||||
|
|
||||||
// 更新用户密码
|
// 更新用户密码
|
||||||
|
// TODO @宋天:不要更新整个对象哈
|
||||||
userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
|
userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
|
||||||
userMapper.updateById(userDO);
|
userMapper.updateById(userDO);
|
||||||
}
|
}
|
||||||
@ -300,6 +301,8 @@ public class SysAuthServiceImpl implements SysAuthService {
|
|||||||
// TODO @芋艿 这一步没必要检验验证码与手机是否匹配,因为是根据验证码去redis中查找手机号,然后根据手机号查询用户
|
// TODO @芋艿 这一步没必要检验验证码与手机是否匹配,因为是根据验证码去redis中查找手机号,然后根据手机号查询用户
|
||||||
// 也就是说 即便黑客以其他方式将验证码发送到自己手机上,最终还是会根据手机号查询用户然后进行重置密码的操作,不存在安全问题
|
// 也就是说 即便黑客以其他方式将验证码发送到自己手机上,最终还是会根据手机号查询用户然后进行重置密码的操作,不存在安全问题
|
||||||
|
|
||||||
|
// TODO @宋天:这块微信在讨论下哈~~~
|
||||||
|
|
||||||
// 校验验证码
|
// 校验验证码
|
||||||
smsCodeService.useSmsCode(userDO.getMobile(), SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
|
smsCodeService.useSmsCode(userDO.getMobile(), SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());
|
||||||
|
|
||||||
|
@ -58,10 +58,14 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
|
|||||||
// 创建验证码
|
// 创建验证码
|
||||||
String code = this.createSmsCode(mobile, scene, createIp);
|
String code = this.createSmsCode(mobile, scene, createIp);
|
||||||
// 发送验证码
|
// 发送验证码
|
||||||
|
// TODO @宋天:这里可以拓展下 SysSmsSceneEnum,支持设置对应的短信模板编号(不同场景的短信文案是不同的)、是否要校验手机号已经注册。这样 Controller 就可以收口成一个接口了。相当于说,不同场景,不同策略
|
||||||
smsCoreService.sendSingleSmsToMember(mobile, null, SysSmsTemplateCodeConstants.USER_SMS_LOGIN,
|
smsCoreService.sendSingleSmsToMember(mobile, null, SysSmsTemplateCodeConstants.USER_SMS_LOGIN,
|
||||||
MapUtil.of("code", code));
|
MapUtil.of("code", code));
|
||||||
|
|
||||||
// 存储手机号与验证码到redis,用于标记
|
// 存储手机号与验证码到redis,用于标记
|
||||||
|
// TODO @宋天:SysSmsCodeDO 表应该足够,无需增加额外的 redis 存储哇
|
||||||
|
// TODO @宋天:Redis 相关的操作,不要散落到业务层,而是写一个它对应的 RedisDAO。这样,实现业务与技术的解耦
|
||||||
|
// TODO @宋天:直接使用 code 作为 key,会存在 2 个问题:1)code 可能会冲突,多个手机号之间;2)缺少前缀。例如说 sms_code_${code}
|
||||||
stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES);
|
stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||||||
*
|
*
|
||||||
* @author 宋天
|
* @author 宋天
|
||||||
*/
|
*/
|
||||||
|
// TODO @宋天:controller 的单测可以不写哈,因为收益太低了。未来我们做 qa 自动化测试
|
||||||
public class SysUserProfileControllerTest {
|
public class SysUserProfileControllerTest {
|
||||||
|
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
@ -35,7 +36,7 @@ public class SysUserProfileControllerTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private SysSmsCodeService smsCodeService;
|
private SysSmsCodeService smsCodeService;
|
||||||
|
|
||||||
@Before
|
@Before // TODO @宋天:使用 junit5 哈
|
||||||
public void setup() {
|
public void setup() {
|
||||||
// 初始化
|
// 初始化
|
||||||
MockitoAnnotations.openMocks(this);
|
MockitoAnnotations.openMocks(this);
|
||||||
@ -52,7 +53,7 @@ public class SysUserProfileControllerTest {
|
|||||||
.content("{\"mobile\":\"15819844280\",\"code\":\"123456\"}}"))
|
.content("{\"mobile\":\"15819844280\",\"code\":\"123456\"}}"))
|
||||||
.andExpect(status().isOk())
|
.andExpect(status().isOk())
|
||||||
.andDo(MockMvcResultHandlers.print());
|
.andDo(MockMvcResultHandlers.print());
|
||||||
|
// TODO @宋天:方法的结尾,不用空行哈
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;
|
import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;
|
||||||
import cn.iocoder.yudao.userserver.BaseDbUnitTest;
|
|
||||||
import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
|
import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;
|
||||||
import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
|
import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;
|
||||||
import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
|
import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
|
||||||
@ -15,7 +14,6 @@ import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSend
|
|||||||
import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
|
import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;
|
||||||
import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;
|
import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;
|
||||||
import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
|
import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;
|
||||||
import cn.iocoder.yudao.userserver.modules.system.service.sms.impl.SysSmsCodeServiceImpl;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
@ -23,14 +21,16 @@ import org.springframework.data.redis.core.StringRedisTemplate;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.*;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static cn.hutool.core.util.RandomUtil.*;
|
import static cn.hutool.core.util.RandomUtil.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
// TODO @芋艿:单测的 review,等逻辑都达成一致后
|
||||||
/**
|
/**
|
||||||
* {@link MbrUserServiceImpl} 的单元测试类
|
* {@link MbrUserServiceImpl} 的单元测试类
|
||||||
*
|
*
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package cn.iocoder.yudao.userserver.modules.system.service;
|
package cn.iocoder.yudao.userserver.modules.system.service;
|
||||||
|
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
|
import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;
|
||||||
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
|
|
||||||
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
|
import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
|
||||||
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
|
import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
|
||||||
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
|
import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialService;
|
||||||
@ -10,11 +8,8 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
|||||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;
|
import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;
|
||||||
import cn.iocoder.yudao.userserver.BaseDbUnitTest;
|
|
||||||
import cn.iocoder.yudao.userserver.config.RedisTestConfiguration;
|
|
||||||
import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
|
import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;
|
||||||
import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
|
import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;
|
||||||
import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;
|
|
||||||
import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthResetPasswordReqVO;
|
import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthResetPasswordReqVO;
|
||||||
import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthUpdatePasswordReqVO;
|
import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthUpdatePasswordReqVO;
|
||||||
import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
|
import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;
|
||||||
@ -28,17 +23,17 @@ import org.springframework.security.authentication.AuthenticationManager;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static cn.hutool.core.util.RandomUtil.randomEle;
|
import static cn.hutool.core.util.RandomUtil.randomEle;
|
||||||
import static cn.hutool.core.util.RandomUtil.randomNumbers;
|
import static cn.hutool.core.util.RandomUtil.randomNumbers;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||||
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.mockito.Mockito.*;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO @芋艿:单测的 review,等逻辑都达成一致后
|
||||||
/**
|
/**
|
||||||
* {@link SysAuthService} 的单元测试类
|
* {@link SysAuthService} 的单元测试类
|
||||||
*
|
*
|
||||||
@ -68,7 +63,6 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
|
|||||||
@Resource
|
@Resource
|
||||||
private SysAuthServiceImpl authService;
|
private SysAuthServiceImpl authService;
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdatePassword_success(){
|
public void testUpdatePassword_success(){
|
||||||
// 准备参数
|
// 准备参数
|
||||||
|
Loading…
Reference in New Issue
Block a user