diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java index 381450e66..ca4830ecf 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApi.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.system.api.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import cn.iocoder.yudao.module.system.enums.ApiConstants; @@ -29,8 +29,8 @@ public interface SmsCodeApi { @ApiOperation("验证短信验证码,并进行使用") CommonResult useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO); - @GetMapping(PREFIX + "/check") + @GetMapping(PREFIX + "/validate") @ApiOperation("检查验证码是否有效") - CommonResult checkSmsCode(@Valid @RequestBody SmsCodeCheckReqDTO reqDTO); + CommonResult validateSmsCode(@Valid @RequestBody SmsCodeValidateReqDTO reqDTO); } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java similarity index 96% rename from yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java rename to yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java index 99107492e..c96d3fa83 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeCheckReqDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/sms/dto/code/SmsCodeValidateReqDTO.java @@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull; @ApiModel("RPC 服务 - 短信验证码的校验 Request DTO") @Data -public class SmsCodeCheckReqDTO { +public class SmsCodeValidateReqDTO { @ApiModelProperty(value = "手机号", required = true, example = "15601691300") @Mobile diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java index 15e59a264..c59d21ea3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/sms/SmsCodeApiImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.system.api.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import cn.iocoder.yudao.module.system.service.sms.SmsCodeService; @@ -35,8 +35,8 @@ public class SmsCodeApiImpl implements SmsCodeApi { } @Override - public CommonResult checkSmsCode(SmsCodeCheckReqDTO reqDTO) { - smsCodeService.checkSmsCode(reqDTO); + public CommonResult validateSmsCode(SmsCodeValidateReqDTO reqDTO) { + smsCodeService.validateSmsCode(reqDTO); return success(true); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java index f71b8a6bd..70cdb2f4c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeService.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.exception.ServiceException; -import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import javax.validation.Valid; @@ -35,6 +35,6 @@ public interface SmsCodeService { * * @param reqDTO 校验请求 */ - void checkSmsCode(@Valid SmsCodeCheckReqDTO reqDTO); + void validateSmsCode(@Valid SmsCodeValidateReqDTO reqDTO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java index 778445dd9..682b89eff 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java @@ -3,11 +3,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.date.LocalDateTimeUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; -import cn.iocoder.yudao.framework.common.util.date.DateUtils; -import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeCheckReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; @@ -16,11 +14,11 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; - import java.time.LocalDateTime; -import java.time.temporal.ChronoUnit; import static cn.hutool.core.util.RandomUtil.randomInt; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.isToday; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** @@ -58,11 +56,11 @@ public class SmsCodeServiceImpl implements SmsCodeService { if (lastSmsCode != null) { if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis() < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁 - throw ServiceExceptionUtil.exception(SMS_CODE_SEND_TOO_FAST); + throw exception(SMS_CODE_SEND_TOO_FAST); } - if (DateUtils.isToday(lastSmsCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限 + if (isToday(lastSmsCode.getCreateTime()) && // 必须是今天,才能计算超过当天的上限 lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。 - throw ServiceExceptionUtil.exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); + throw exception(SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); } // TODO 芋艿:提升,每个 IP 每天可发送数量 // TODO 芋艿:提升,每个 IP 每小时可发送数量 @@ -71,7 +69,7 @@ public class SmsCodeServiceImpl implements SmsCodeService { // 创建验证码记录 String code = String.valueOf(randomInt(smsCodeProperties.getBeginCode(), smsCodeProperties.getEndCode() + 1)); SmsCodeDO newSmsCode = SmsCodeDO.builder().mobile(mobile).code(code).scene(scene) - .todayIndex(lastSmsCode != null && DateUtils.isToday(lastSmsCode.getCreateTime()) ? lastSmsCode.getTodayIndex() + 1 : 1) + .todayIndex(lastSmsCode != null && isToday(lastSmsCode.getCreateTime()) ? lastSmsCode.getTodayIndex() + 1 : 1) .createIp(ip).used(false).build(); smsCodeMapper.insert(newSmsCode); return code; @@ -80,32 +78,32 @@ public class SmsCodeServiceImpl implements SmsCodeService { @Override public void useSmsCode(SmsCodeUseReqDTO reqDTO) { // 检测验证码是否有效 - SmsCodeDO lastSmsCode = this.checkSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); + SmsCodeDO lastSmsCode = validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); // 使用验证码 smsCodeMapper.updateById(SmsCodeDO.builder().id(lastSmsCode.getId()) .used(true).usedTime(LocalDateTime.now()).usedIp(reqDTO.getUsedIp()).build()); } @Override - public void checkSmsCode(SmsCodeCheckReqDTO reqDTO) { - checkSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); + public void validateSmsCode(SmsCodeValidateReqDTO reqDTO) { + validateSmsCode0(reqDTO.getMobile(), reqDTO.getCode(), reqDTO.getScene()); } - public SmsCodeDO checkSmsCode0(String mobile, String code, Integer scene) { + private SmsCodeDO validateSmsCode0(String mobile, String code, Integer scene) { // 校验验证码 SmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, code, scene); // 若验证码不存在,抛出异常 if (lastSmsCode == null) { - throw ServiceExceptionUtil.exception(SMS_CODE_NOT_FOUND); + throw exception(SMS_CODE_NOT_FOUND); } // 超过时间 if (LocalDateTimeUtil.between(lastSmsCode.getCreateTime(), LocalDateTime.now()).toMillis() >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期 - throw ServiceExceptionUtil.exception(SMS_CODE_EXPIRED); + throw exception(SMS_CODE_EXPIRED); } // 判断验证码是否已被使用 if (Boolean.TRUE.equals(lastSmsCode.getUsed())) { - throw ServiceExceptionUtil.exception(SMS_CODE_USED); + throw exception(SMS_CODE_USED); } return lastSmsCode; } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java index 168af02d9..11a51b7c6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java @@ -15,7 +15,6 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import javax.annotation.Resource; - import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; @@ -118,8 +117,8 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { // 调用 smsChannelService.deleteSmsChannel(id); - // 校验数据不存在了 - assertNull(smsChannelMapper.selectById(id)); + // 校验数据不存在了 + assertNull(smsChannelMapper.selectById(id)); // 校验调用 verify(smsProducer, times(1)).sendSmsChannelRefreshMessage(); } @@ -178,31 +177,31 @@ public class SmsChannelServiceTest extends BaseDbUnitTest { @Test public void testGetSmsChannelPage() { - // mock 数据 - SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 - o.setSignature("芋道源码"); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCreateTime(buildTime(2020, 12, 12)); - }); - smsChannelMapper.insert(dbSmsChannel); - // 测试 signature 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码"))); - // 测试 status 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 createTime 不匹配 - smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); - // 准备参数 - SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); - reqVO.setSignature("芋道"); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); + // mock 数据 + SmsChannelDO dbSmsChannel = randomPojo(SmsChannelDO.class, o -> { // 等会查询到 + o.setSignature("芋道源码"); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCreateTime(buildTime(2020, 12, 12)); + }); + smsChannelMapper.insert(dbSmsChannel); + // 测试 signature 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码"))); + // 测试 status 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 createTime 不匹配 + smsChannelMapper.insert(cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11)))); + // 准备参数 + SmsChannelPageReqVO reqVO = new SmsChannelPageReqVO(); + reqVO.setSignature("芋道"); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setCreateTime(buildBetweenTime(2020, 12, 1, 2020, 12, 24)); - // 调用 - PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSmsChannel, pageResult.getList().get(0)); + // 调用 + PageResult pageResult = smsChannelService.getSmsChannelPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsChannel, pageResult.getList().get(0)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java new file mode 100644 index 000000000..e50d025af --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java @@ -0,0 +1,209 @@ +package cn.iocoder.yudao.module.system.service.sms; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; +import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; +import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; +import cn.iocoder.yudao.module.system.framework.sms.SmsCodeProperties; +import com.baomidou.mybatisplus.annotation.DbType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; + +import javax.annotation.Resource; +import java.time.Duration; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.randomEle; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@Import(SmsCodeServiceImpl.class) +public class SmsCodeServiceImplTest extends BaseDbUnitTest { + + @Resource + private SmsCodeServiceImpl smsCodeService; + + @Resource + private SmsCodeMapper smsCodeMapper; + + @MockBean + private SmsCodeProperties smsCodeProperties; + @MockBean + private SmsSendService smsSendService; + + @BeforeEach + public void setUp() { + when(smsCodeProperties.getExpireTimes()).thenReturn(Duration.ofMinutes(5)); + when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMinutes(1)); + when(smsCodeProperties.getSendMaximumQuantityPerDay()).thenReturn(10); + when(smsCodeProperties.getBeginCode()).thenReturn(9999); + when(smsCodeProperties.getEndCode()).thenReturn(9999); + } + + @Test + public void sendSmsCode_success() { + // 准备参数 + SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene()); + }); + // mock 方法 + SqlConstants.init(DbType.MYSQL); + + // 调用 + smsCodeService.sendSmsCode(reqDTO); + // 断言 code 验证码 + SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null); + assertPojoEquals(reqDTO, smsCodeDO); + assertEquals("9999", smsCodeDO.getCode()); + assertEquals(1, smsCodeDO.getTodayIndex()); + assertFalse(smsCodeDO.getUsed()); + // 断言调用 + verify(smsSendService).sendSingleSms(eq(reqDTO.getMobile()), isNull(), isNull(), + eq("user-sms-login"), eq(MapUtil.of("code", "9999"))); + } + + @Test + public void sendSmsCode_tooFast() { + // mock 数据 + SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class, + o -> o.setMobile("15601691300").setTodayIndex(1)); + smsCodeMapper.insert(smsCodeDO); + // 准备参数 + SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene()); + }); + // mock 方法 + SqlConstants.init(DbType.MYSQL); + + // 调用,并断言异常 + assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), + SMS_CODE_SEND_TOO_FAST); + } + + @Test + public void sendSmsCode_exceedDay() { + // mock 数据 + SmsCodeDO smsCodeDO = randomPojo(SmsCodeDO.class, + o -> o.setMobile("15601691300").setTodayIndex(10).setCreateTime(LocalDateTime.now())); + smsCodeMapper.insert(smsCodeDO); + // 准备参数 + SmsCodeSendReqDTO reqDTO = randomPojo(SmsCodeSendReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(SmsSceneEnum.MEMBER_LOGIN.getScene()); + }); + // mock 方法 + SqlConstants.init(DbType.MYSQL); + when(smsCodeProperties.getSendFrequency()).thenReturn(Duration.ofMillis(0)); + + // 调用,并断言异常 + assertServiceException(() -> smsCodeService.sendSmsCode(reqDTO), + SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); + } + + @Test + public void testUseSmsCode_success() { + // 准备参数 + SmsCodeUseReqDTO reqDTO = randomPojo(SmsCodeUseReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(randomEle(SmsSceneEnum.values()).getScene()); + }); + // mock 数据 + SqlConstants.init(DbType.MYSQL); + smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> { + o.setMobile(reqDTO.getMobile()).setScene(reqDTO.getScene()) + .setCode(reqDTO.getCode()).setUsed(false); + })); + + // 调用 + smsCodeService.useSmsCode(reqDTO); + // 断言 + SmsCodeDO smsCodeDO = smsCodeMapper.selectOne(null); + assertTrue(smsCodeDO.getUsed()); + assertNotNull(smsCodeDO.getUsedTime()); + assertEquals(reqDTO.getUsedIp(), smsCodeDO.getUsedIp()); + } + + @Test + public void validateSmsCode_success() { + // 准备参数 + SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(randomEle(SmsSceneEnum.values()).getScene()); + }); + // mock 数据 + SqlConstants.init(DbType.MYSQL); + smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile()) + .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false))); + + // 调用 + smsCodeService.validateSmsCode(reqDTO); + } + + @Test + public void validateSmsCode_notFound() { + // 准备参数 + SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(randomEle(SmsSceneEnum.values()).getScene()); + }); + // mock 数据 + SqlConstants.init(DbType.MYSQL); + + // 调用,并断言异常 + assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO), + SMS_CODE_NOT_FOUND); + } + + @Test + public void validateSmsCode_expired() { + // 准备参数 + SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(randomEle(SmsSceneEnum.values()).getScene()); + }); + // mock 数据 + SqlConstants.init(DbType.MYSQL); + smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile()) + .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(false) + .setCreateTime(LocalDateTime.now().minusMinutes(6)))); + + // 调用,并断言异常 + assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO), + SMS_CODE_EXPIRED); + } + + @Test + public void validateSmsCode_used() { + // 准备参数 + SmsCodeValidateReqDTO reqDTO = randomPojo(SmsCodeValidateReqDTO.class, o -> { + o.setMobile("15601691300"); + o.setScene(randomEle(SmsSceneEnum.values()).getScene()); + }); + // mock 数据 + SqlConstants.init(DbType.MYSQL); + smsCodeMapper.insert(randomPojo(SmsCodeDO.class, o -> o.setMobile(reqDTO.getMobile()) + .setScene(reqDTO.getScene()).setCode(reqDTO.getCode()).setUsed(true) + .setCreateTime(LocalDateTime.now()))); + + // 调用,并断言异常 + assertServiceException(() -> smsCodeService.validateSmsCode(reqDTO), + SMS_CODE_USED); + } + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java similarity index 78% rename from yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java rename to yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java index f5045aaeb..2380ca09e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsLogServiceImplTest.java @@ -34,7 +34,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @Import(SmsLogServiceImpl.class) -public class SmsLogServiceTest extends BaseDbUnitTest { +public class SmsLogServiceImplTest extends BaseDbUnitTest { @Resource private SmsLogServiceImpl smsLogService; @@ -44,47 +44,47 @@ public class SmsLogServiceTest extends BaseDbUnitTest { @Test public void testGetSmsLogPage() { - // mock 数据 - SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 - o.setChannelId(1L); - o.setTemplateId(10L); - o.setMobile("15601691300"); - o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - o.setSendTime(buildTime(2020, 11, 11)); - o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - o.setReceiveTime(buildTime(2021, 11, 11)); - }); - smsLogMapper.insert(dbSmsLog); - // 测试 channelId 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); - // 测试 templateId 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); - // 测试 mobile 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); - // 测试 sendStatus 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); - // 测试 sendTime 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); - // 测试 receiveStatus 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); - // 测试 receiveTime 不匹配 - smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); - // 准备参数 - SmsLogPageReqVO reqVO = new SmsLogPageReqVO(); - reqVO.setChannelId(1L); - reqVO.setTemplateId(10L); - reqVO.setMobile("156"); - reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); - reqVO.setSendTime(buildBetweenTime(2020, 11, 1, 2020, 11, 30)); - reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); - reqVO.setReceiveTime(buildBetweenTime(2021, 11, 1, 2021, 11, 30)); + // mock 数据 + SmsLogDO dbSmsLog = randomSmsLogDO(o -> { // 等会查询到 + o.setChannelId(1L); + o.setTemplateId(10L); + o.setMobile("15601691300"); + o.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + o.setSendTime(buildTime(2020, 11, 11)); + o.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + o.setReceiveTime(buildTime(2021, 11, 11)); + }); + smsLogMapper.insert(dbSmsLog); + // 测试 channelId 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L))); + // 测试 templateId 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L))); + // 测试 mobile 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999"))); + // 测试 sendStatus 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SmsSendStatusEnum.IGNORE.getStatus()))); + // 测试 sendTime 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12)))); + // 测试 receiveStatus 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SmsReceiveStatusEnum.SUCCESS.getStatus()))); + // 测试 receiveTime 不匹配 + smsLogMapper.insert(cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12)))); + // 准备参数 + SmsLogPageReqVO reqVO = new SmsLogPageReqVO(); + reqVO.setChannelId(1L); + reqVO.setTemplateId(10L); + reqVO.setMobile("156"); + reqVO.setSendStatus(SmsSendStatusEnum.INIT.getStatus()); + reqVO.setSendTime(buildBetweenTime(2020, 11, 1, 2020, 11, 30)); + reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); + reqVO.setReceiveTime(buildBetweenTime(2021, 11, 1, 2021, 11, 30)); - // 调用 - PageResult pageResult = smsLogService.getSmsLogPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); + // 调用 + PageResult pageResult = smsLogService.getSmsLogPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsLog, pageResult.getList().get(0)); } @Test @@ -124,11 +124,11 @@ public class SmsLogServiceTest extends BaseDbUnitTest { reqVO.setReceiveStatus(SmsReceiveStatusEnum.INIT.getStatus()); reqVO.setReceiveTime(buildBetweenTime(2021, 11, 1, 2021, 11, 30)); - // 调用 - List list = smsLogService.getSmsLogList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSmsLog, list.get(0)); + // 调用 + List list = smsLogService.getSmsLogList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbSmsLog, list.get(0)); } @Test diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java deleted file mode 100644 index 37b361449..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceTest.java +++ /dev/null @@ -1,288 +0,0 @@ -package cn.iocoder.yudao.module.system.service.sms; - -import cn.hutool.core.map.MapUtil; -import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage; -import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; -import cn.iocoder.yudao.module.system.service.member.MemberService; -import cn.iocoder.yudao.module.system.service.user.AdminUserService; -import org.assertj.core.util.Lists; -import org.junit.jupiter.api.Test; -import org.mockito.InjectMocks; -import org.mockito.Mock; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.*; - -public class SmsSendServiceTest extends BaseMockitoUnitTest { - - @InjectMocks - private SmsSendServiceImpl smsService; - - @Mock - private AdminUserService adminUserService; - @Mock - private MemberService memberService; - @Mock - private SmsChannelService smsChannelService; - @Mock - private SmsTemplateService smsTemplateService; - @Mock - private SmsLogService smsLogService; - @Mock - private SmsProducer smsProducer; - - @Mock - private SmsClientFactory smsClientFactory; - - @Test - public void testSendSingleSmsToAdmin() { - // 准备参数 - Long userId = randomLongId(); - String templateCode = randomString(); - Map templateParams = MapUtil.builder().put("code", "1234") - .put("op", "login").build(); - // mock adminUserService 的方法 - AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setMobile("15601691300")); - when(adminUserService.getUser(eq(userId))).thenReturn(user); - - // mock SmsTemplateService 的方法 - SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setContent("验证码为{code}, 操作为{op}"); - o.setParams(Lists.newArrayList("code", "op")); - }); - when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); - String content = randomString(); - when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) - .thenReturn(content); - // mock SmsChannelService 的方法 - SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel); - // mock SmsLogService 的方法 - Long smsLogId = randomLongId(); - when(smsLogService.createSmsLog(eq(user.getMobile()), eq(userId), eq(UserTypeEnum.ADMIN.getValue()), eq(Boolean.TRUE), eq(template), - eq(content), eq(templateParams))).thenReturn(smsLogId); - - // 调用 - Long resultSmsLogId = smsService.sendSingleSmsToAdmin(null, userId, templateCode, templateParams); - // 断言 - assertEquals(smsLogId, resultSmsLogId); - // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(user.getMobile()), - eq(template.getChannelId()), eq(template.getApiTemplateId()), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); - } - - @Test - public void testSendSingleSmsToUser() { - // 准备参数 - Long userId = randomLongId(); - String templateCode = randomString(); - Map templateParams = MapUtil.builder().put("code", "1234") - .put("op", "login").build(); - // mock adminUserService 的方法 - String mobile = "15601691300"; - when(memberService.getMemberUserMobile(eq(userId))).thenReturn(mobile); - - // mock SmsTemplateService 的方法 - SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setContent("验证码为{code}, 操作为{op}"); - o.setParams(Lists.newArrayList("code", "op")); - }); - when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); - String content = randomString(); - when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) - .thenReturn(content); - // mock SmsChannelService 的方法 - SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel); - // mock SmsLogService 的方法 - Long smsLogId = randomLongId(); - when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(UserTypeEnum.MEMBER.getValue()), eq(Boolean.TRUE), eq(template), - eq(content), eq(templateParams))).thenReturn(smsLogId); - - // 调用 - Long resultSmsLogId = smsService.sendSingleSmsToMember(null, userId, templateCode, templateParams); - // 断言 - assertEquals(smsLogId, resultSmsLogId); - // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), - eq(template.getChannelId()), eq(template.getApiTemplateId()), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); - } - - /** - * 发送成功,当短信模板开启时 - */ - @Test - public void testSendSingleSms_successWhenSmsTemplateEnable() { - // 准备参数 - String mobile = randomString(); - Long userId = randomLongId(); - Integer userType = randomEle(UserTypeEnum.values()).getValue(); - String templateCode = randomString(); - Map templateParams = MapUtil.builder().put("code", "1234") - .put("op", "login").build(); - // mock SmsTemplateService 的方法 - SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setContent("验证码为{code}, 操作为{op}"); - o.setParams(Lists.newArrayList("code", "op")); - }); - when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); - String content = randomString(); - when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) - .thenReturn(content); - // mock SmsChannelService 的方法 - SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel); - // mock SmsLogService 的方法 - Long smsLogId = randomLongId(); - when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.TRUE), eq(template), - eq(content), eq(templateParams))).thenReturn(smsLogId); - - // 调用 - Long resultSmsLogId = smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); - // 断言 - assertEquals(smsLogId, resultSmsLogId); - // 断言调用 - verify(smsProducer).sendSmsSendMessage(eq(smsLogId), eq(mobile), - eq(template.getChannelId()), eq(template.getApiTemplateId()), - eq(Lists.newArrayList(new KeyValue<>("code", "1234"), new KeyValue<>("op", "login")))); - } - - /** - * 发送成功,当短信模板关闭时 - */ - @Test - public void testSendSingleSms_successWhenSmsTemplateDisable() { - // 准备参数 - String mobile = randomString(); - Long userId = randomLongId(); - Integer userType = randomEle(UserTypeEnum.values()).getValue(); - String templateCode = randomString(); - Map templateParams = MapUtil.builder().put("code", "1234") - .put("op", "login").build(); - // mock SmsTemplateService 的方法 - SmsTemplateDO template = randomPojo(SmsTemplateDO.class, o -> { - o.setStatus(CommonStatusEnum.DISABLE.getStatus()); - o.setContent("验证码为{code}, 操作为{op}"); - o.setParams(Lists.newArrayList("code", "op")); - }); - when(smsTemplateService.getSmsTemplateByCodeFromCache(eq(templateCode))).thenReturn(template); - String content = randomString(); - when(smsTemplateService.formatSmsTemplateContent(eq(template.getContent()), eq(templateParams))) - .thenReturn(content); - // mock SmsChannelService 的方法 - SmsChannelDO smsChannel = randomPojo(SmsChannelDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())); - when(smsChannelService.getSmsChannel(eq(template.getChannelId()))).thenReturn(smsChannel); - // mock SmsLogService 的方法 - Long smsLogId = randomLongId(); - when(smsLogService.createSmsLog(eq(mobile), eq(userId), eq(userType), eq(Boolean.FALSE), eq(template), - eq(content), eq(templateParams))).thenReturn(smsLogId); - - // 调用 - Long resultSmsLogId = smsService.sendSingleSms(mobile, userId, userType, templateCode, templateParams); - // 断言 - assertEquals(smsLogId, resultSmsLogId); - // 断言调用 - verify(smsProducer, times(0)).sendSmsSendMessage(anyLong(), anyString(), - anyLong(), any(), anyList()); - } - - @Test - public void testCheckSmsTemplateValid_notExists() { - // 准备参数 - String templateCode = randomString(); - // mock 方法 - - // 调用,并断言异常 - assertServiceException(() -> smsService.validateSmsTemplate(templateCode), - SMS_SEND_TEMPLATE_NOT_EXISTS); - } - - @Test - public void testBuildTemplateParams_paramMiss() { - // 准备参数 - SmsTemplateDO template = randomPojo(SmsTemplateDO.class, - o -> o.setParams(Lists.newArrayList("code"))); - Map templateParams = new HashMap<>(); - // mock 方法 - - // 调用,并断言异常 - assertServiceException(() -> smsService.buildTemplateParams(template, templateParams), - SMS_SEND_MOBILE_TEMPLATE_PARAM_MISS, "code"); - } - - @Test - public void testCheckMobile_notExists() { - // 准备参数 - // mock 方法 - - // 调用,并断言异常 - assertServiceException(() -> smsService.validateMobile(null), - SMS_SEND_MOBILE_NOT_EXISTS); - } - - @Test - @SuppressWarnings("unchecked") - public void testDoSendSms() { - // 准备参数 - SmsSendMessage message = randomPojo(SmsSendMessage.class); - // mock SmsClientFactory 的方法 - SmsClient smsClient = spy(SmsClient.class); - when(smsClientFactory.getSmsClient(eq(message.getChannelId()))).thenReturn(smsClient); - // mock SmsClient 的方法 - SmsCommonResult sendResult = randomPojo(SmsCommonResult.class, SmsSendRespDTO.class); - when(smsClient.sendSms(eq(message.getLogId()), eq(message.getMobile()), eq(message.getApiTemplateId()), - eq(message.getTemplateParams()))).thenReturn(sendResult); - - // 调用 - smsService.doSendSms(message); - // 断言 - verify(smsLogService).updateSmsSendResult(eq(message.getLogId()), - eq(sendResult.getCode()), eq(sendResult.getMsg()), eq(sendResult.getApiCode()), - eq(sendResult.getApiMsg()), eq(sendResult.getApiRequestId()), eq(sendResult.getData().getSerialNo())); - } - - @Test - public void testReceiveSmsStatus() throws Throwable { - // 准备参数 - String channelCode = randomString(); - String text = randomString(); - // mock SmsClientFactory 的方法 - SmsClient smsClient = spy(SmsClient.class); - when(smsClientFactory.getSmsClient(eq(channelCode))).thenReturn(smsClient); - // mock SmsClient 的方法 - List receiveResults = randomPojoList(SmsReceiveRespDTO.class); - - // 调用 - smsService.receiveSmsStatus(channelCode, text); - // 断言 - receiveResults.forEach(result -> smsLogService.updateSmsReceiveResult(eq(result.getLogId()), eq(result.getSuccess()), - eq(result.getReceiveTime()), eq(result.getErrorCode()), eq(result.getErrorCode()))); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java similarity index 83% rename from yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java rename to yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java index b5ec9ca99..cc41abb9c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java @@ -1,14 +1,5 @@ package cn.iocoder.yudao.module.system.service.sms; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; -import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; -import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; -import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; -import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; -import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -19,6 +10,15 @@ import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult; import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateExportReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateUpdateReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; +import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; +import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsTemplateMapper; +import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum; +import cn.iocoder.yudao.module.system.mq.producer.sms.SmsProducer; import com.google.common.collect.Lists; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; @@ -30,20 +30,18 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; -import static cn.hutool.core.bean.BeanUtil.getFieldValue; import static cn.hutool.core.util.RandomUtil.randomEle; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @Import(SmsTemplateServiceImpl.class) -public class SmsTemplateServiceTest extends BaseDbUnitTest { +public class SmsTemplateServiceImplTest extends BaseDbUnitTest { @Resource private SmsTemplateServiceImpl smsTemplateService; @@ -176,8 +174,8 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { // 调用 smsTemplateService.deleteSmsTemplate(id); - // 校验数据不存在了 - assertNull(smsTemplateMapper.selectById(id)); + // 校验数据不存在了 + assertNull(smsTemplateMapper.selectById(id)); // 校验调用 verify(smsProducer, times(1)).sendSmsTemplateRefreshMessage(); } @@ -193,47 +191,47 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { @Test public void testGetSmsTemplatePage() { - // mock 数据 - SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到 - o.setType(SmsTemplateTypeEnum.PROMOTION.getType()); - o.setStatus(CommonStatusEnum.ENABLE.getStatus()); - o.setCode("tudou"); - o.setContent("芋道源码"); - o.setApiTemplateId("yunai"); - o.setChannelId(1L); - o.setCreateTime(buildTime(2021, 11, 11)); - }); - smsTemplateMapper.insert(dbSmsTemplate); - // 测试 type 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); - // 测试 status 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); - // 测试 code 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma"))); - // 测试 content 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码"))); - // 测试 apiTemplateId 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai"))); - // 测试 channelId 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L))); - // 测试 createTime 不匹配 - smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); - // 准备参数 - SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO(); - reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); - reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); - reqVO.setCode("tu"); - reqVO.setContent("芋道"); - reqVO.setApiTemplateId("yu"); - reqVO.setChannelId(1L); - reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 1),buildTime(2021, 12, 1)})); + // mock 数据 + SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到 + o.setType(SmsTemplateTypeEnum.PROMOTION.getType()); + o.setStatus(CommonStatusEnum.ENABLE.getStatus()); + o.setCode("tudou"); + o.setContent("芋道源码"); + o.setApiTemplateId("yunai"); + o.setChannelId(1L); + o.setCreateTime(buildTime(2021, 11, 11)); + }); + smsTemplateMapper.insert(dbSmsTemplate); + // 测试 type 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType()))); + // 测试 status 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); + // 测试 code 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma"))); + // 测试 content 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码"))); + // 测试 apiTemplateId 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai"))); + // 测试 channelId 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L))); + // 测试 createTime 不匹配 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12)))); + // 准备参数 + SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO(); + reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType()); + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); + reqVO.setCode("tu"); + reqVO.setContent("芋道"); + reqVO.setApiTemplateId("yu"); + reqVO.setChannelId(1L); + reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 1),buildTime(2021, 12, 1)})); - // 调用 - PageResult pageResult = smsTemplateService.getSmsTemplatePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbSmsTemplate, pageResult.getList().get(0)); + // 调用 + PageResult pageResult = smsTemplateService.getSmsTemplatePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbSmsTemplate, pageResult.getList().get(0)); } @Test @@ -273,11 +271,11 @@ public class SmsTemplateServiceTest extends BaseDbUnitTest { reqVO.setChannelId(1L); reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021, 11, 1),buildTime(2021, 12, 1)})); - // 调用 - List list = smsTemplateService.getSmsTemplateList(reqVO); - // 断言 - assertEquals(1, list.size()); - assertPojoEquals(dbSmsTemplate, list.get(0)); + // 调用 + List list = smsTemplateService.getSmsTemplateList(reqVO); + // 断言 + assertEquals(1, list.size()); + assertPojoEquals(dbSmsTemplate, list.get(0)); } @Test diff --git a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql index 1be69f28b..6d9dbf4b9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql +++ b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql @@ -14,6 +14,7 @@ DELETE FROM "system_users"; DELETE FROM "system_sms_channel"; DELETE FROM "system_sms_template"; DELETE FROM "system_sms_log"; +DELETE FROM "system_sms_code"; DELETE FROM "system_error_code"; DELETE FROM "system_social_user"; DELETE FROM "system_social_user_bind"; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql index b00c9168e..89074492c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql @@ -377,6 +377,24 @@ CREATE TABLE IF NOT EXISTS "system_sms_log" ( PRIMARY KEY ("id") ) COMMENT '短信日志'; +CREATE TABLE IF NOT EXISTS "system_sms_code" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "mobile" varchar(11) NOT NULL, + "code" varchar(11) NOT NULL, + "scene" bigint NOT NULL, + "create_ip" varchar NOT NULL, + "today_index" int NOT NULL, + "used" bit NOT NULL DEFAULT FALSE, + "used_time" timestamp DEFAULT NULL, + "used_ip" varchar NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT '短信日志'; + CREATE TABLE IF NOT EXISTS "system_error_code" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "type" tinyint NOT NULL DEFAULT '0', @@ -568,19 +586,19 @@ CREATE TABLE IF NOT EXISTS "system_oauth2_code" ( ) COMMENT 'OAuth2 刷新令牌'; CREATE TABLE IF NOT EXISTS "system_mail_account" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "mail" varchar NOT NULL, - "username" varchar NOT NULL, - "password" varchar NOT NULL, - "host" varchar NOT NULL, - "port" int NOT NULL, - "ssl_enable" bit NOT NULL, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "mail" varchar NOT NULL, + "username" varchar NOT NULL, + "password" varchar NOT NULL, + "host" varchar NOT NULL, + "port" int NOT NULL, + "ssl_enable" bit NOT NULL, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") ) COMMENT '邮箱账号表'; CREATE TABLE IF NOT EXISTS "system_mail_template" ( @@ -603,28 +621,28 @@ CREATE TABLE IF NOT EXISTS "system_mail_template" ( ) COMMENT '邮件模版表'; CREATE TABLE IF NOT EXISTS "system_mail_log" ( - "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, - "user_id" bigint, - "user_type" varchar, - "to_mail" varchar NOT NULL, - "account_id" bigint NOT NULL, - "from_mail" varchar NOT NULL, - "template_id" bigint NOT NULL, - "template_code" varchar NOT NULL, - "template_nickname" varchar, - "template_title" varchar NOT NULL, - "template_content" varchar NOT NULL, - "template_params" varchar NOT NULL, - "send_status" varchar NOT NULL, - "send_time" datetime, - "send_message_id" varchar, - "send_exception" varchar, - "creator" varchar DEFAULT '', - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updater" varchar DEFAULT '', - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - "deleted" bit NOT NULL DEFAULT FALSE, - PRIMARY KEY ("id") + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "user_id" bigint, + "user_type" varchar, + "to_mail" varchar NOT NULL, + "account_id" bigint NOT NULL, + "from_mail" varchar NOT NULL, + "template_id" bigint NOT NULL, + "template_code" varchar NOT NULL, + "template_nickname" varchar, + "template_title" varchar NOT NULL, + "template_content" varchar NOT NULL, + "template_params" varchar NOT NULL, + "send_status" varchar NOT NULL, + "send_time" datetime, + "send_message_id" varchar, + "send_exception" varchar, + "creator" varchar DEFAULT '', + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar DEFAULT '', + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") ) COMMENT '邮件日志表'; -- 将该建表 SQL 语句,添加到 yudao-module-system-biz 模块的 test/resources/sql/create_tables.sql 文件里