code review 修改密码等的单元测试

This commit is contained in:
YunaiV 2021-11-21 12:05:34 +08:00
parent 42ce5c75fd
commit e2b76ee0e5
12 changed files with 25 additions and 20 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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);

View File

@ -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;

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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());

View File

@ -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 个问题1code 可能会冲突多个手机号之间2缺少前缀例如说 sms_code_${code}
stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES); stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES);
} }

View File

@ -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 @宋天方法的结尾不用空行哈
} }

View File

@ -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} 的单元测试类
* *

View File

@ -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(){
// 准备参数 // 准备参数