完善 SmsCodeServiceImpl 单元测试
							parent
							
								
									5a18223bc3
								
							
						
					
					
						commit
						ac25dbe286
					
				| 
						 | 
				
			
			@ -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<Boolean> useSmsCode(@Valid @RequestBody SmsCodeUseReqDTO reqDTO);
 | 
			
		||||
 | 
			
		||||
    @GetMapping(PREFIX + "/check")
 | 
			
		||||
    @GetMapping(PREFIX + "/validate")
 | 
			
		||||
    @ApiOperation("检查验证码是否有效")
 | 
			
		||||
    CommonResult<Boolean> checkSmsCode(@Valid @RequestBody SmsCodeCheckReqDTO reqDTO);
 | 
			
		||||
    CommonResult<Boolean> validateSmsCode(@Valid @RequestBody SmsCodeValidateReqDTO reqDTO);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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<Boolean> checkSmsCode(SmsCodeCheckReqDTO reqDTO) {
 | 
			
		||||
        smsCodeService.checkSmsCode(reqDTO);
 | 
			
		||||
    public CommonResult<Boolean> validateSmsCode(SmsCodeValidateReqDTO reqDTO) {
 | 
			
		||||
        smsCodeService.validateSmsCode(reqDTO);
 | 
			
		||||
        return success(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -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<String, Object> templateParams = MapUtil.<String, Object>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<String, Object> templateParams = MapUtil.<String, Object>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<String, Object> templateParams = MapUtil.<String, Object>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<String, Object> templateParams = MapUtil.<String, Object>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<String, Object> 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<SmsSendRespDTO> 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<SmsReceiveRespDTO> 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())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -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";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue