mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-26 01:01:52 +08:00
邮箱模块:完善 template 的单元测试
This commit is contained in:
parent
0895ee7d98
commit
c0b029b244
@ -41,6 +41,11 @@ public class LocalDateTimeUtils {
|
||||
return LocalDateTime.of(year, mouth, day, 0, 0, 0);
|
||||
}
|
||||
|
||||
public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1,
|
||||
int year2, int mouth2, int day2) {
|
||||
return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前时间是否在该时间范围内
|
||||
*
|
||||
|
@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
|
||||
import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -55,6 +56,7 @@ public class MailTemplateServiceImpl implements MailTemplateService {
|
||||
*
|
||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||
*/
|
||||
@Getter
|
||||
private volatile Map<String, MailTemplateDO> mailTemplateCache;
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,163 @@
|
||||
package cn.iocoder.yudao.module.system.service.mail;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateCreateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplateUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.mail.MailTemplateMapper;
|
||||
import cn.iocoder.yudao.module.system.mq.producer.mail.MailProducer;
|
||||
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.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
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.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.MAIL_TEMPLATE_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link MailTemplateServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(MailTemplateServiceImpl.class)
|
||||
public class MailTemplateServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private MailTemplateServiceImpl mailTemplateService;
|
||||
|
||||
@Resource
|
||||
private MailTemplateMapper mailTemplateMapper;
|
||||
|
||||
@MockBean
|
||||
private MailProducer mailProducer;
|
||||
|
||||
@Test
|
||||
public void testInitLocalCache() {
|
||||
MailTemplateDO templateDO01 = randomPojo(MailTemplateDO.class);
|
||||
mailTemplateMapper.insert(templateDO01);
|
||||
MailTemplateDO templateDO02 = randomPojo(MailTemplateDO.class);
|
||||
mailTemplateMapper.insert(templateDO02);
|
||||
|
||||
// 调用
|
||||
mailTemplateService.initLocalCache();
|
||||
// 断言 mailTemplateCache 缓存
|
||||
Map<String, MailTemplateDO> mailTemplateCache = mailTemplateService.getMailTemplateCache();
|
||||
assertPojoEquals(templateDO01, mailTemplateCache.get(templateDO01.getCode()));
|
||||
assertPojoEquals(templateDO02, mailTemplateCache.get(templateDO02.getCode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateMailTemplate_success() {
|
||||
// 准备参数
|
||||
MailTemplateCreateReqVO reqVO = randomPojo(MailTemplateCreateReqVO.class);
|
||||
|
||||
// 调用
|
||||
Long mailTemplateId = mailTemplateService.createMailTemplate(reqVO);
|
||||
// 断言
|
||||
assertNotNull(mailTemplateId);
|
||||
// 校验记录的属性是否正确
|
||||
MailTemplateDO mailTemplate = mailTemplateMapper.selectById(mailTemplateId);
|
||||
assertPojoEquals(reqVO, mailTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMailTemplate_success() {
|
||||
// mock 数据
|
||||
MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
|
||||
mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class, o -> {
|
||||
o.setId(dbMailTemplate.getId()); // 设置更新的 ID
|
||||
});
|
||||
|
||||
// 调用
|
||||
mailTemplateService.updateMailTemplate(reqVO);
|
||||
// 校验是否更新正确
|
||||
MailTemplateDO mailTemplate = mailTemplateMapper.selectById(reqVO.getId()); // 获取最新的
|
||||
assertPojoEquals(reqVO, mailTemplate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateMailTemplate_notExists() {
|
||||
// 准备参数
|
||||
MailTemplateUpdateReqVO reqVO = randomPojo(MailTemplateUpdateReqVO.class);
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> mailTemplateService.updateMailTemplate(reqVO), MAIL_TEMPLATE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteMailTemplate_success() {
|
||||
// mock 数据
|
||||
MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class);
|
||||
mailTemplateMapper.insert(dbMailTemplate);// @Sql: 先插入出一条存在的数据
|
||||
// 准备参数
|
||||
Long id = dbMailTemplate.getId();
|
||||
|
||||
// 调用
|
||||
mailTemplateService.deleteMailTemplate(id);
|
||||
// 校验数据不存在了
|
||||
assertNull(mailTemplateMapper.selectById(id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeleteMailTemplate_notExists() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
|
||||
// 调用, 并断言异常
|
||||
assertServiceException(() -> mailTemplateService.deleteMailTemplate(id), MAIL_TEMPLATE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMailTemplatePage() {
|
||||
// mock 数据
|
||||
MailTemplateDO dbMailTemplate = randomPojo(MailTemplateDO.class, o -> { // 等会查询到
|
||||
o.setName("源码");
|
||||
o.setCode("test_01");
|
||||
o.setAccountId(1L);
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setCreateTime(buildTime(2023, 2, 3));
|
||||
});
|
||||
mailTemplateMapper.insert(dbMailTemplate);
|
||||
// 测试 name 不匹配
|
||||
mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setName("芋道")));
|
||||
// 测试 code 不匹配
|
||||
mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCode("test_02")));
|
||||
// 测试 accountId 不匹配
|
||||
mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setAccountId(2L)));
|
||||
// 测试 status 不匹配
|
||||
mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||
// 测试 createTime 不匹配
|
||||
mailTemplateMapper.insert(cloneIgnoreId(dbMailTemplate, o -> o.setCreateTime(buildTime(2023, 1, 5))));
|
||||
// 准备参数
|
||||
MailTemplatePageReqVO reqVO = new MailTemplatePageReqVO();
|
||||
reqVO.setName("源");
|
||||
reqVO.setCode("est_01");
|
||||
reqVO.setAccountId(1L);
|
||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 5));
|
||||
|
||||
// 调用
|
||||
PageResult<MailTemplateDO> pageResult = mailTemplateService.getMailTemplatePage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbMailTemplate, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
@ -26,3 +26,4 @@ DELETE FROM "system_oauth2_access_token";
|
||||
DELETE FROM "system_oauth2_refresh_token";
|
||||
DELETE FROM "system_oauth2_code";
|
||||
DELETE FROM "system_mail_account";
|
||||
DELETE FROM "system_mail_template";
|
||||
|
@ -582,3 +582,22 @@ CREATE TABLE IF NOT EXISTS "system_mail_account" (
|
||||
"deleted" bit NOT NULL DEFAULT FALSE,
|
||||
PRIMARY KEY ("id")
|
||||
) COMMENT '邮箱账号表';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "system_mail_template" (
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"code" varchar NOT NULL,
|
||||
"account_id" bigint NOT NULL,
|
||||
"nickname" varchar,
|
||||
"title" varchar NOT NULL,
|
||||
"content" varchar NOT NULL,
|
||||
"params" varchar NOT NULL,
|
||||
"status" varchar NOT NULL,
|
||||
"remark" 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 '邮件模版表';
|
||||
|
@ -42,3 +42,12 @@ export function getMailTemplatePage(query) {
|
||||
params: query
|
||||
})
|
||||
}
|
||||
|
||||
// 发送测试邮件
|
||||
export function sendMail(data) {
|
||||
return request({
|
||||
url: '/system/mail-template/send-mail',
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ export function getSmsTemplatePage(query) {
|
||||
})
|
||||
}
|
||||
|
||||
// 创建短信模板
|
||||
// 发送测试短信
|
||||
export function sendSms(data) {
|
||||
return request({
|
||||
url: '/system/sms-template/send-sms',
|
||||
|
@ -44,6 +44,7 @@
|
||||
<el-table-column label="模板编码" align="center" prop="code" />
|
||||
<el-table-column label="模板名称" align="center" prop="name" />
|
||||
<el-table-column label="模板标题" align="center" prop="title" />
|
||||
<el-table-column label="模板内容" align="center" prop="content" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="邮箱账号" align="center" prop="accountId" width="200">
|
||||
<template v-slot="scope">
|
||||
{{ accountOptions.find(account => account.id === scope.row.accountId)?.mail }}
|
||||
@ -55,14 +56,15 @@
|
||||
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" align="center" prop="remark" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
|
||||
<template v-slot="scope">
|
||||
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="150">
|
||||
<template v-slot="scope">
|
||||
<el-button size="mini" type="text" icon="el-icon-share" @click="handleSend(scope.row)"
|
||||
v-hasPermi="['system:mail-template:send-mail']">测试</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['system:mail-template:update']">修改</el-button>
|
||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||
@ -112,11 +114,30 @@
|
||||
<el-button @click="cancel">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 对话框(发送邮件) -->
|
||||
<el-dialog title="测试发送邮件" :visible.sync="sendOpen" width="500px" append-to-body>
|
||||
<el-form ref="sendForm" :model="sendForm" :rules="sendRules" label-width="140px">
|
||||
<el-form-item label="模板内容" prop="content">
|
||||
<el-input v-model="sendForm.content" type="textarea" placeholder="请输入模板内容" readonly />
|
||||
</el-form-item>
|
||||
<el-form-item label="收件邮箱" prop="mail">
|
||||
<el-input v-model="sendForm.mail" placeholder="请输入收件邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item v-for="param in sendForm.params" :key="param" :label="'参数 {' + param + '}'" :prop="'templateParams.' + param">
|
||||
<el-input v-model="sendForm.templateParams[param]" :placeholder="'请输入 ' + param + ' 参数'" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitSendForm">确 定</el-button>
|
||||
<el-button @click="cancelSend">取 消</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { createMailTemplate, updateMailTemplate, deleteMailTemplate, getMailTemplate, getMailTemplatePage } from "@/api/system/mail/template";
|
||||
import { createMailTemplate, updateMailTemplate, deleteMailTemplate, getMailTemplate, getMailTemplatePage, sendMail } from "@/api/system/mail/template";
|
||||
import Editor from '@/components/Editor';
|
||||
import { CommonStatusEnum } from "@/utils/constants";
|
||||
import { getSimpleMailAccountList } from "@/api/system/mail/account";
|
||||
@ -130,8 +151,6 @@ export default {
|
||||
return {
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
// 导出遮罩层
|
||||
exportLoading: false,
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
// 总条数
|
||||
@ -164,7 +183,18 @@ export default {
|
||||
status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
|
||||
},
|
||||
// 邮箱账号
|
||||
accountOptions: []
|
||||
accountOptions: [],
|
||||
|
||||
// 发送邮箱
|
||||
sendOpen: false,
|
||||
sendForm: {
|
||||
params: [], // 模板的参数列表
|
||||
},
|
||||
sendRules: {
|
||||
mail: [{ required: true, message: "收件邮箱不能为空", trigger: "blur" }],
|
||||
templateCode: [{ required: true, message: "模版编码不能为空", trigger: "blur" }],
|
||||
templateParams: { }
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
@ -263,7 +293,56 @@ export default {
|
||||
this.getList();
|
||||
this.$modal.msgSuccess("删除成功");
|
||||
}).catch(() => {});
|
||||
},
|
||||
/** 发送短息按钮 */
|
||||
handleSend(row) {
|
||||
this.resetSend(row);
|
||||
// 设置参数
|
||||
this.sendForm.content = row.content;
|
||||
this.sendForm.params = row.params;
|
||||
this.sendForm.templateCode = row.code;
|
||||
this.sendForm.templateParams = row.params.reduce(function(obj, item) {
|
||||
obj[item] = undefined;
|
||||
return obj;
|
||||
}, {});
|
||||
// 根据 row 重置 rules
|
||||
this.sendRules.templateParams = row.params.reduce(function(obj, item) {
|
||||
obj[item] = { required: true, message: '参数 ' + item + " 不能为空", trigger: "change" };
|
||||
return obj;
|
||||
}, {});
|
||||
// 设置打开
|
||||
this.sendOpen = true;
|
||||
},
|
||||
/** 重置发送邮箱的表单 */
|
||||
resetSend() {
|
||||
// 根据 row 重置表单
|
||||
this.sendForm = {
|
||||
content: undefined,
|
||||
params: undefined,
|
||||
mobile: undefined,
|
||||
templateCode: undefined,
|
||||
templateParams: {}
|
||||
};
|
||||
this.resetForm("sendForm");
|
||||
},
|
||||
/** 取消发送邮箱 */
|
||||
cancelSend() {
|
||||
this.sendOpen = false;
|
||||
this.resetSend();
|
||||
},
|
||||
/** 提交按钮 */
|
||||
submitSendForm() {
|
||||
this.$refs["sendForm"].validate(valid => {
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// 添加的提交
|
||||
sendMail(this.sendForm).then(response => {
|
||||
this.$modal.msgSuccess("提交发送成功!发送结果,见发送日志编号:" + response.data);
|
||||
this.sendOpen = false;
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
@ -216,7 +216,7 @@ export default {
|
||||
},
|
||||
sendSmsRules: {
|
||||
mobile: [{ required: true, message: "手机不能为空", trigger: "blur" }],
|
||||
templateCode: [{ required: true, message: "手机不能为空", trigger: "blur" }],
|
||||
templateCode: [{ required: true, message: "模版编码不能为空", trigger: "blur" }],
|
||||
templateParams: { }
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user