短信模板的创建 Test 单元测试

This commit is contained in:
YunaiV
2021-04-05 23:52:24 +08:00
parent 58d368cfdc
commit fbbcd2717a
7 changed files with 305 additions and 132 deletions

View File

@ -13,7 +13,7 @@ import java.util.List;
@Mapper
public interface SysSmsTemplateMapper extends BaseMapperX<SysSmsTemplateDO> {
default SysSmsTemplateDO selectOneByCode(String code) {
default SysSmsTemplateDO selectByCode(String code) {
return selectOne("code", code);
}

View File

@ -80,9 +80,11 @@ public interface SysErrorCodeConstants {
// ========== 短信渠道 1002011000 ==========
ErrorCode SMS_CHANNEL_NOT_EXISTS = new ErrorCode(1002011000, "短信渠道不存在");
ErrorCode SMS_CHANNEL_DISABLE = new ErrorCode(1002011001, "短信渠道不处于开启状态,不允许选择");
// ========== 短信模板 1002011000 ==========
ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}}】的短信模板");
// ========== 短信发送 1002012000 ==========
ErrorCode SMS_SEND_MOBILE_NOT_EXISTS = new ErrorCode(1002012000, "手机号不存在");

View File

@ -1,24 +1,31 @@
package cn.iocoder.dashboard.modules.system.service.sms.impl;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO;
import cn.iocoder.dashboard.modules.system.convert.sms.SysSmsTemplateConvert;
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsTemplateMapper;
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsChannelService;
import cn.iocoder.dashboard.modules.system.service.sms.SysSmsTemplateService;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Pattern;
import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_TEMPLATE_NOT_EXISTS;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
/**
* 短信模板Service实现类
@ -29,12 +36,20 @@ import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SM
@Service
public class SysSmsTemplateServiceImpl implements SysSmsTemplateService {
/**
* 正则表达式,匹配 {} 中的变量
*/
private static final Pattern PATTERN_PARAMS = Pattern.compile("\\{(.*?)}");
@Resource
private SysSmsTemplateMapper smsTemplateMapper;
@Resource
private SysSmsChannelService smsChannelService;
@Override
public SysSmsTemplateDO getSmsTemplateByCode(String code) {
return smsTemplateMapper.selectOneByCode(code);
return smsTemplateMapper.selectByCode(code);
}
@Override
@ -42,13 +57,25 @@ public class SysSmsTemplateServiceImpl implements SysSmsTemplateService {
return StrUtil.format(content, params);
}
@VisibleForTesting
public List<String> parseTemplateContentParams(String content) {
return ReUtil.findAllGroup1(PATTERN_PARAMS, content);
}
@Override
public Long createSmsTemplate(SysSmsTemplateCreateReqVO createReqVO) {
// 校验短信渠道
SysSmsChannelDO channelDO = checkSmsChannel(createReqVO.getChannelId());
// 校验短信编码是否重复
checkSmsTemplateCodeDuplicate(null, createReqVO.getCode());
// 插入
SysSmsTemplateDO smsTemplate = SysSmsTemplateConvert.INSTANCE.convert(createReqVO);
smsTemplateMapper.insert(smsTemplate);
SysSmsTemplateDO template = SysSmsTemplateConvert.INSTANCE.convert(createReqVO);
template.setParams(parseTemplateContentParams(template.getContent()));
template.setChannelCode(channelDO.getCode());
smsTemplateMapper.insert(template);
// 返回
return smsTemplate.getId();
return template.getId();
}
@Override
@ -94,4 +121,29 @@ public class SysSmsTemplateServiceImpl implements SysSmsTemplateService {
return smsTemplateMapper.selectList(exportReqVO);
}
private SysSmsChannelDO checkSmsChannel(Long channelId) {
SysSmsChannelDO channelDO = smsChannelService.getSmsChannel(channelId);
if (channelDO == null) {
throw exception(SMS_CHANNEL_NOT_EXISTS);
}
if (!Objects.equals(channelDO.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
throw exception(SMS_CHANNEL_DISABLE);
}
return channelDO;
}
private void checkSmsTemplateCodeDuplicate(Long id, String code) {
SysSmsTemplateDO template = smsTemplateMapper.selectByCode(code);
if (template == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的字典类型
if (id == null) {
throw exception(SMS_TEMPLATE_CODE_DUPLICATE);
}
if (!template.getId().equals(id)) {
throw exception(SMS_TEMPLATE_CODE_DUPLICATE);
}
}
}

View File

@ -1,27 +1,37 @@
package cn.iocoder.dashboard.modules.system.service.sms;
import cn.iocoder.dashboard.BaseDbUnitTest;
import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
import cn.iocoder.dashboard.common.pojo.PageResult;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateCreateReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateExportReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplatePageReqVO;
import cn.iocoder.dashboard.modules.system.controller.sms.vo.template.SysSmsTemplateUpdateReqVO;
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsChannelDO;
import cn.iocoder.dashboard.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.sms.SysSmsTemplateMapper;
import cn.iocoder.dashboard.modules.system.enums.sms.SysSmsTemplateTypeEnum;
import cn.iocoder.dashboard.modules.system.service.sms.impl.SysSmsTemplateServiceImpl;
import cn.iocoder.dashboard.util.collection.ArrayUtils;
import cn.iocoder.dashboard.util.object.ObjectUtils;
import com.google.common.collect.Lists;
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.util.List;
import java.util.function.Consumer;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.SMS_TEMPLATE_NOT_EXISTS;
import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
import static cn.iocoder.dashboard.util.RandomUtils.randomLongId;
import static cn.iocoder.dashboard.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link SysSmsTemplateServiceImpl} 的单元测试类
@ -37,10 +47,35 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
@Resource
private SysSmsTemplateMapper smsTemplateMapper;
@MockBean
private SysSmsChannelService smsChannelService;
@Test
public void testParseTemplateContentParams() {
// 准备参数
String content = "正在进行登录操作{operation},您的验证码是{code}";
// mock 方法
// 调用
List<String> params = smsTemplateService.parseTemplateContentParams(content);
// 断言
assertEquals(Lists.newArrayList("operation", "code"), params);
}
@Test
public void testCreateSmsTemplate_success() {
// 准备参数
SysSmsTemplateCreateReqVO reqVO = randomPojo(SysSmsTemplateCreateReqVO.class);
SysSmsTemplateCreateReqVO reqVO = randomPojo(SysSmsTemplateCreateReqVO.class, o -> {
o.setContent("正在进行登录操作{operation},您的验证码是{code}");
o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的泛微
});
// mock 方法
SysSmsChannelDO channelDO = randomPojo(SysSmsChannelDO.class, o -> {
o.setId(reqVO.getChannelId());
o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
});
when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
// 调用
Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO);
@ -49,6 +84,8 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
// 校验记录的属性是否正确
SysSmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId);
assertPojoEquals(reqVO, smsTemplate);
assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams());
assertEquals(channelDO.getCode(), smsTemplate.getChannelCode());
}
@Test
@ -80,7 +117,7 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
@Test
public void testDeleteSmsTemplate_success() {
// mock 数据
SysSmsTemplateDO dbSmsTemplate = randomPojo(SysSmsTemplateDO.class);
SysSmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbSmsTemplate.getId();
@ -191,4 +228,13 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
assertPojoEquals(dbSmsTemplate, list.get(0));
}
@SafeVarargs
private static SysSmsTemplateDO randomSmsTemplateDO(Consumer<SysSmsTemplateDO>... consumers) {
Consumer<SysSmsTemplateDO> consumer = (o) -> {
o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
o.setType(randomEle(SysSmsTemplateTypeEnum.values()).getType()); // 保证 type 的泛微
};
return randomPojo(SysSmsTemplateDO.class, ArrayUtils.append(consumer, consumers));
}
}

View File

@ -358,3 +358,23 @@ CREATE TABLE IF NOT EXISTS "sys_sms_channel" (
"deleted" bit NOT NULL DEFAULT FALSE,
PRIMARY KEY ("id")
) COMMENT '短信渠道';
CREATE TABLE "sys_sms_template" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"type" tinyint NOT NULL,
"status" tinyint NOT NULL,
"code" varchar(63) NOT NULL,
"name" varchar(63) NOT NULL,
"content" varchar(255) NOT NULL,
"params" varchar(255) NOT NULL,
"remark" varchar(255) DEFAULT NULL,
"api_template_id" varchar(63) NOT NULL,
"channel_id" bigint NOT NULL,
"channel_code" varchar(63) NOT 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 '短信模板';