houzhongyi
2024-07-11 e7c1260db32209a078a962aaa0ad5492c35774fb
提交 | 用户 | 时间
e7c126 1 package com.iailab.module.system.service.sms;
H 2
3 import cn.hutool.core.map.MapUtil;
4 import com.iailab.framework.common.enums.CommonStatusEnum;
5 import com.iailab.framework.common.pojo.PageResult;
6 import com.iailab.framework.common.util.collection.ArrayUtils;
7 import com.iailab.framework.common.util.object.ObjectUtils;
8 import com.iailab.module.system.framework.sms.core.client.SmsClient;
9 import com.iailab.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO;
10 import com.iailab.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum;
11 import com.iailab.framework.test.core.ut.BaseDbUnitTest;
12 import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO;
13 import com.iailab.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO;
14 import com.iailab.module.system.dal.dataobject.sms.SmsChannelDO;
15 import com.iailab.module.system.dal.dataobject.sms.SmsTemplateDO;
16 import com.iailab.module.system.dal.mysql.sms.SmsTemplateMapper;
17 import com.iailab.module.system.enums.sms.SmsTemplateTypeEnum;
18 import com.google.common.collect.Lists;
19 import org.junit.jupiter.api.Test;
20 import org.springframework.boot.test.mock.mockito.MockBean;
21 import org.springframework.context.annotation.Import;
22
23 import javax.annotation.Resource;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.function.Consumer;
27
28 import static cn.hutool.core.util.RandomUtil.randomEle;
29 import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
30 import static com.iailab.framework.common.util.date.LocalDateTimeUtils.buildTime;
31 import static com.iailab.framework.test.core.util.AssertUtils.assertPojoEquals;
32 import static com.iailab.framework.test.core.util.AssertUtils.assertServiceException;
33 import static com.iailab.framework.test.core.util.RandomUtils.*;
34 import static com.iailab.module.system.enums.ErrorCodeConstants.*;
35 import static org.junit.jupiter.api.Assertions.*;
36 import static org.mockito.ArgumentMatchers.eq;
37 import static org.mockito.Mockito.when;
38
39 @Import(SmsTemplateServiceImpl.class)
40 public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
41
42     @Resource
43     private SmsTemplateServiceImpl smsTemplateService;
44
45     @Resource
46     private SmsTemplateMapper smsTemplateMapper;
47
48     @MockBean
49     private SmsChannelService smsChannelService;
50     @MockBean
51     private SmsClient smsClient;
52
53     @Test
54     public void testFormatSmsTemplateContent() {
55         // 准备参数
56         String content = "正在进行登录操作{operation},您的验证码是{code}";
57         Map<String, Object> params = MapUtil.<String, Object>builder("operation", "登录")
58                 .put("code", "1234").build();
59
60         // 调用
61         String result = smsTemplateService.formatSmsTemplateContent(content, params);
62         // 断言
63         assertEquals("正在进行登录操作登录,您的验证码是1234", result);
64     }
65
66     @Test
67     public void testParseTemplateContentParams() {
68         // 准备参数
69         String content = "正在进行登录操作{operation},您的验证码是{code}";
70         // mock 方法
71
72         // 调用
73         List<String> params = smsTemplateService.parseTemplateContentParams(content);
74         // 断言
75         assertEquals(Lists.newArrayList("operation", "code"), params);
76     }
77
78     @Test
79     @SuppressWarnings("unchecked")
80     public void testCreateSmsTemplate_success() throws Throwable {
81         // 准备参数
82         SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
83             o.setContent("正在进行登录操作{operation},您的验证码是{code}");
84             o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
85             o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
86         }).setId(null); // 防止 id 被赋值
87         // mock Channel 的方法
88         SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
89             o.setId(reqVO.getChannelId());
90             o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
91         });
92         when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
93         // mock 获得 API 短信模板成功
94         when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
95         when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(
96                 randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus())));
97
98         // 调用
99         Long smsTemplateId = smsTemplateService.createSmsTemplate(reqVO);
100         // 断言
101         assertNotNull(smsTemplateId);
102         // 校验记录的属性是否正确
103         SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(smsTemplateId);
104         assertPojoEquals(reqVO, smsTemplate, "id");
105         assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams());
106         assertEquals(channelDO.getCode(), smsTemplate.getChannelCode());
107     }
108
109     @Test
110     @SuppressWarnings("unchecked")
111     public void testUpdateSmsTemplate_success() throws Throwable {
112         // mock 数据
113         SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
114         smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
115         // 准备参数
116         SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class, o -> {
117             o.setId(dbSmsTemplate.getId()); // 设置更新的 ID
118             o.setContent("正在进行登录操作{operation},您的验证码是{code}");
119             o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
120             o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
121         });
122         // mock 方法
123         SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
124             o.setId(reqVO.getChannelId());
125             o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
126         });
127         when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
128         // mock 获得 API 短信模板成功
129         when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
130         when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(
131                 randomPojo(SmsTemplateRespDTO.class, o -> o.setAuditStatus(SmsTemplateAuditStatusEnum.SUCCESS.getStatus())));
132
133         // 调用
134         smsTemplateService.updateSmsTemplate(reqVO);
135         // 校验是否更新正确
136         SmsTemplateDO smsTemplate = smsTemplateMapper.selectById(reqVO.getId()); // 获取最新的
137         assertPojoEquals(reqVO, smsTemplate);
138         assertEquals(Lists.newArrayList("operation", "code"), smsTemplate.getParams());
139         assertEquals(channelDO.getCode(), smsTemplate.getChannelCode());
140     }
141
142     @Test
143     public void testUpdateSmsTemplate_notExists() {
144         // 准备参数
145         SmsTemplateSaveReqVO reqVO = randomPojo(SmsTemplateSaveReqVO.class);
146
147         // 调用, 并断言异常
148         assertServiceException(() -> smsTemplateService.updateSmsTemplate(reqVO), SMS_TEMPLATE_NOT_EXISTS);
149     }
150
151     @Test
152     public void testDeleteSmsTemplate_success() {
153         // mock 数据
154         SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
155         smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
156         // 准备参数
157         Long id = dbSmsTemplate.getId();
158
159         // 调用
160         smsTemplateService.deleteSmsTemplate(id);
161         // 校验数据不存在了
162         assertNull(smsTemplateMapper.selectById(id));
163     }
164
165     @Test
166     public void testDeleteSmsTemplate_notExists() {
167         // 准备参数
168         Long id = randomLongId();
169
170         // 调用, 并断言异常
171         assertServiceException(() -> smsTemplateService.deleteSmsTemplate(id), SMS_TEMPLATE_NOT_EXISTS);
172     }
173
174     @Test
175     public void testGetSmsTemplate() {
176         // mock 数据
177         SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
178         smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
179         // 准备参数
180         Long id = dbSmsTemplate.getId();
181
182         // 调用
183         SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplate(id);
184         // 校验
185         assertPojoEquals(dbSmsTemplate, smsTemplate);
186     }
187
188     @Test
189     public void testGetSmsTemplateByCodeFromCache() {
190         // mock 数据
191         SmsTemplateDO dbSmsTemplate = randomSmsTemplateDO();
192         smsTemplateMapper.insert(dbSmsTemplate);// @Sql: 先插入出一条存在的数据
193         // 准备参数
194         String code = dbSmsTemplate.getCode();
195
196         // 调用
197         SmsTemplateDO smsTemplate = smsTemplateService.getSmsTemplateByCodeFromCache(code);
198         // 校验
199         assertPojoEquals(dbSmsTemplate, smsTemplate);
200     }
201
202     @Test
203     public void testGetSmsTemplatePage() {
204         // mock 数据
205         SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> { // 等会查询到
206             o.setType(SmsTemplateTypeEnum.PROMOTION.getType());
207             o.setStatus(CommonStatusEnum.ENABLE.getStatus());
208             o.setCode("tudou");
209             o.setContent("iailab");
210             o.setApiTemplateId("yunai");
211             o.setChannelId(1L);
212             o.setCreateTime(buildTime(2021, 11, 11));
213         });
214         smsTemplateMapper.insert(dbSmsTemplate);
215         // 测试 type 不匹配
216         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
217         // 测试 status 不匹配
218         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
219         // 测试 code 不匹配
220         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
221         // 测试 content 不匹配
222         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
223         // 测试 apiTemplateId 不匹配
224         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
225         // 测试 channelId 不匹配
226         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
227         // 测试 createTime 不匹配
228         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
229         // 准备参数
230         SmsTemplatePageReqVO reqVO = new SmsTemplatePageReqVO();
231         reqVO.setType(SmsTemplateTypeEnum.PROMOTION.getType());
232         reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
233         reqVO.setCode("tu");
234         reqVO.setContent("平台");
235         reqVO.setApiTemplateId("yu");
236         reqVO.setChannelId(1L);
237         reqVO.setCreateTime(buildBetweenTime(2021, 11, 1, 2021, 12, 1));
238
239         // 调用
240         PageResult<SmsTemplateDO> pageResult = smsTemplateService.getSmsTemplatePage(reqVO);
241         // 断言
242         assertEquals(1, pageResult.getTotal());
243         assertEquals(1, pageResult.getList().size());
244         assertPojoEquals(dbSmsTemplate, pageResult.getList().get(0));
245     }
246
247     @Test
248     public void testGetSmsTemplateCountByChannelId() {
249         // mock 数据
250         SmsTemplateDO dbSmsTemplate = randomPojo(SmsTemplateDO.class, o -> o.setChannelId(1L));
251         smsTemplateMapper.insert(dbSmsTemplate);
252         // 测试 channelId 不匹配
253         smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
254         // 准备参数
255         Long channelId = 1L;
256
257         // 调用
258         Long count = smsTemplateService.getSmsTemplateCountByChannelId(channelId);
259         // 断言
260         assertEquals(1, count);
261     }
262
263     @Test
264     public void testValidateSmsChannel_success() {
265         // 准备参数
266         Long channelId = randomLongId();
267         // mock 方法
268         SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
269             o.setId(channelId);
270             o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 开启,创建必须处于这个状态
271         });
272         when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
273
274         // 调用
275         SmsChannelDO returnChannelDO = smsTemplateService.validateSmsChannel(channelId);
276         // 断言
277         assertPojoEquals(returnChannelDO, channelDO);
278     }
279
280     @Test
281     public void testValidateSmsChannel_notExists() {
282         // 准备参数
283         Long channelId = randomLongId();
284
285         // 调用,校验异常
286         assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
287                 SMS_CHANNEL_NOT_EXISTS);
288     }
289
290     @Test
291     public void testValidateSmsChannel_disable() {
292         // 准备参数
293         Long channelId = randomLongId();
294         // mock 方法
295         SmsChannelDO channelDO = randomPojo(SmsChannelDO.class, o -> {
296             o.setId(channelId);
297             o.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 保证 status 禁用,触发失败
298         });
299         when(smsChannelService.getSmsChannel(eq(channelId))).thenReturn(channelDO);
300
301         // 调用,校验异常
302         assertServiceException(() -> smsTemplateService.validateSmsChannel(channelId),
303                 SMS_CHANNEL_DISABLE);
304     }
305
306     @Test
307     public void testValidateDictDataValueUnique_success() {
308         // 调用,成功
309         smsTemplateService.validateSmsTemplateCodeDuplicate(randomLongId(), randomString());
310     }
311
312     @Test
313     public void testValidateSmsTemplateCodeDuplicate_valueDuplicateForCreate() {
314         // 准备参数
315         String code = randomString();
316         // mock 数据
317         smsTemplateMapper.insert(randomSmsTemplateDO(o -> o.setCode(code)));
318
319         // 调用,校验异常
320         assertServiceException(() -> smsTemplateService.validateSmsTemplateCodeDuplicate(null, code),
321                 SMS_TEMPLATE_CODE_DUPLICATE, code);
322     }
323
324     @Test
325     public void testValidateDictDataValueUnique_valueDuplicateForUpdate() {
326         // 准备参数
327         Long id = randomLongId();
328         String code = randomString();
329         // mock 数据
330         smsTemplateMapper.insert(randomSmsTemplateDO(o -> o.setCode(code)));
331
332         // 调用,校验异常
333         assertServiceException(() -> smsTemplateService.validateSmsTemplateCodeDuplicate(id, code),
334                 SMS_TEMPLATE_CODE_DUPLICATE, code);
335     }
336
337     // ========== 随机对象 ==========
338
339     @SafeVarargs
340     private static SmsTemplateDO randomSmsTemplateDO(Consumer<SmsTemplateDO>... consumers) {
341         Consumer<SmsTemplateDO> consumer = (o) -> {
342             o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
343             o.setType(randomEle(SmsTemplateTypeEnum.values()).getType()); // 保证 type 的 范围
344         };
345         return randomPojo(SmsTemplateDO.class, ArrayUtils.append(consumer, consumers));
346     }
347
348 }