完善 FileConfig 的单元测试

pull/2/head
YunaiV 2022-03-16 20:47:17 +08:00
parent 659023bb35
commit cdcecd0d4a
5 changed files with 165 additions and 21 deletions

View File

@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.infra.convert.file.FileConfigConvert;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Scheduled;
@ -58,6 +59,7 @@ public class FileConfigServiceImpl implements FileConfigService {
/**
*
*/
@Getter
private volatile Date maxUpdateTime;
@Resource
@ -65,6 +67,7 @@ public class FileConfigServiceImpl implements FileConfigService {
/**
* Master FileClient {@link FileConfigDO#getMaster()}
*/
@Getter
private FileClient masterFileClient;
@Resource

View File

@ -1,25 +1,42 @@
package cn.iocoder.yudao.module.infra.service.file;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.file.core.client.FileClient;
import cn.iocoder.yudao.framework.file.core.client.FileClientConfig;
import cn.iocoder.yudao.framework.file.core.client.FileClientFactory;
import cn.iocoder.yudao.framework.file.core.client.local.LocalFileClientConfig;
import cn.iocoder.yudao.framework.file.core.enums.FileStorageEnum;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigCreateReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigPageReqVO;
import cn.iocoder.yudao.module.infra.controller.admin.file.vo.config.FileConfigUpdateReqVO;
import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileConfigDO;
import cn.iocoder.yudao.module.infra.dal.mysql.file.FileConfigMapper;
import cn.iocoder.yudao.module.infra.mq.producer.file.FileConfigProducer;
import cn.iocoder.yudao.module.infra.test.BaseDbUnitTest;
import org.junit.jupiter.api.Disabled;
import lombok.Data;
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 javax.validation.Validator;
import java.io.Serializable;
import java.util.Map;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
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.infra.enums.ErrorCodeConstants.FILE_CONFIG_DELETE_FAIL_MASTER;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_CONFIG_NOT_EXISTS;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
/**
* {@link FileConfigServiceImpl}
@ -35,10 +52,44 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
@Resource
private FileConfigMapper fileConfigMapper;
@MockBean
private FileConfigProducer fileConfigProducer;
@MockBean
private Validator validator;
@MockBean
private FileClientFactory fileClientFactory;
@Test
public void testInitLocalCache() {
// mock 数据
FileConfigDO configDO1 = randomFileConfigDO().setId(1L).setMaster(true);
fileConfigMapper.insert(configDO1);
FileConfigDO configDO2 = randomFileConfigDO().setId(2L).setMaster(false);
fileConfigMapper.insert(configDO2);
// mock fileClientFactory 获得 master
FileClient masterFileClient = mock(FileClient.class);
when(fileClientFactory.getFileClient(eq(1L))).thenReturn(masterFileClient);
// 调用
fileConfigService.initFileClients();
// 断言 fileClientFactory 调用
verify(fileClientFactory).createOrUpdateFileClient(eq(1L),
eq(configDO1.getStorage()), eq(configDO1.getConfig()));
verify(fileClientFactory).createOrUpdateFileClient(eq(2L),
eq(configDO2.getStorage()), eq(configDO2.getConfig()));
assertSame(masterFileClient, fileConfigService.getMasterFileClient());
// 断言 maxUpdateTime 缓存
assertEquals(max(configDO1.getUpdateTime(), configDO2.getUpdateTime()),
fileConfigService.getMaxUpdateTime());
}
@Test
public void testCreateFileConfig_success() {
// 准备参数
FileConfigCreateReqVO reqVO = randomPojo(FileConfigCreateReqVO.class);
Map<String, Object> config = MapUtil.<String, Object>builder().put("basePath", "/yunai")
.put("domain", "https://www.iocoder.cn").build();
FileConfigCreateReqVO reqVO = randomPojo(FileConfigCreateReqVO.class,
o -> o.setStorage(FileStorageEnum.LOCAL.getStorage()).setConfig(config));
// 调用
Long fileConfigId = fileConfigService.createFileConfig(reqVO);
@ -46,24 +97,37 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
assertNotNull(fileConfigId);
// 校验记录的属性是否正确
FileConfigDO fileConfig = fileConfigMapper.selectById(fileConfigId);
assertPojoEquals(reqVO, fileConfig);
assertPojoEquals(reqVO, fileConfig, "config");
assertFalse(fileConfig.getMaster());
assertEquals("/yunai", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
assertEquals("https://www.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
// verify 调用
verify(fileConfigProducer).sendFileConfigRefreshMessage();
}
@Test
public void testUpdateFileConfig_success() {
// mock 数据
FileConfigDO dbFileConfig = randomPojo(FileConfigDO.class);
FileConfigDO dbFileConfig = randomPojo(FileConfigDO.class, o -> o.setStorage(FileStorageEnum.LOCAL.getStorage())
.setConfig(new LocalFileClientConfig().setBasePath("/yunai").setDomain("https://www.iocoder.cn")));
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
FileConfigUpdateReqVO reqVO = randomPojo(FileConfigUpdateReqVO.class, o -> {
o.setId(dbFileConfig.getId()); // 设置更新的 ID
Map<String, Object> config = MapUtil.<String, Object>builder().put("basePath", "/yunai2")
.put("domain", "https://doc.iocoder.cn").build();
o.setConfig(config);
});
// 调用
fileConfigService.updateFileConfig(reqVO);
// 校验是否更新正确
FileConfigDO fileConfig = fileConfigMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, fileConfig);
assertPojoEquals(reqVO, fileConfig, "config");
assertEquals("/yunai2", ((LocalFileClientConfig) fileConfig.getConfig()).getBasePath());
assertEquals("https://doc.iocoder.cn", ((LocalFileClientConfig) fileConfig.getConfig()).getDomain());
// verify 调用
verify(fileConfigProducer).sendFileConfigRefreshMessage();
}
@Test
@ -75,10 +139,33 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
assertServiceException(() -> fileConfigService.updateFileConfig(reqVO), FILE_CONFIG_NOT_EXISTS);
}
@Test
public void testUpdateFileConfigMaster_success() {
// mock 数据
FileConfigDO dbFileConfig = randomFileConfigDO().setMaster(false);
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
FileConfigDO masterFileConfig = randomFileConfigDO().setMaster(true);
fileConfigMapper.insert(masterFileConfig);// @Sql: 先插入出一条存在的数据
// 调用
fileConfigService.updateFileConfigMaster(dbFileConfig.getId());
// 断言数据
assertTrue(fileConfigMapper.selectById(dbFileConfig.getId()).getMaster());
assertFalse(fileConfigMapper.selectById(masterFileConfig.getId()).getMaster());
// verify 调用
verify(fileConfigProducer).sendFileConfigRefreshMessage();
}
@Test
public void testUpdateFileConfigMaster_notExists() {
// 调用, 并断言异常
assertServiceException(() -> fileConfigService.updateFileConfigMaster(randomLongId()), FILE_CONFIG_NOT_EXISTS);
}
@Test
public void testDeleteFileConfig_success() {
// mock 数据
FileConfigDO dbFileConfig = randomPojo(FileConfigDO.class);
FileConfigDO dbFileConfig = randomFileConfigDO().setMaster(false);
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbFileConfig.getId();
@ -87,6 +174,8 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
fileConfigService.deleteFileConfig(id);
// 校验数据不存在了
assertNull(fileConfigMapper.selectById(id));
// verify 调用
verify(fileConfigProducer).sendFileConfigRefreshMessage();
}
@Test
@ -99,27 +188,36 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
}
@Test
@Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
public void testDeleteFileConfig_master() {
// mock 数据
FileConfigDO dbFileConfig = randomFileConfigDO().setMaster(true);
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbFileConfig.getId();
// 调用, 并断言异常
assertServiceException(() -> fileConfigService.deleteFileConfig(id), FILE_CONFIG_DELETE_FAIL_MASTER);
}
@Test
public void testGetFileConfigPage() {
// mock 数据
FileConfigDO dbFileConfig = randomPojo(FileConfigDO.class, o -> { // 等会查询到
o.setName(null);
o.setStorage(null);
o.setCreateTime(null);
});
FileConfigDO dbFileConfig = randomFileConfigDO().setName("芋道源码")
.setStorage(FileStorageEnum.LOCAL.getStorage());
dbFileConfig.setCreateTime(buildTime(2022, 11, 11));// 等会查询到
fileConfigMapper.insert(dbFileConfig);
// 测试 name 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setName(null)));
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setName("源码")));
// 测试 storage 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setStorage(null)));
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setStorage(FileStorageEnum.DB.getStorage())));
// 测试 createTime 不匹配
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setCreateTime(null)));
fileConfigMapper.insert(cloneIgnoreId(dbFileConfig, o -> o.setCreateTime(buildTime(2022, 12, 12))));
// 准备参数
FileConfigPageReqVO reqVO = new FileConfigPageReqVO();
reqVO.setName(null);
reqVO.setStorage(null);
reqVO.setBeginCreateTime(null);
reqVO.setEndCreateTime(null);
reqVO.setName("芋道");
reqVO.setStorage(FileStorageEnum.LOCAL.getStorage());
reqVO.setBeginCreateTime(buildTime(2022, 11, 10));
reqVO.setEndCreateTime(buildTime(2022, 11, 12));
// 调用
PageResult<FileConfigDO> pageResult = fileConfigService.getFileConfigPage(reqVO);
@ -129,4 +227,30 @@ public class FileConfigServiceImplTest extends BaseDbUnitTest {
assertPojoEquals(dbFileConfig, pageResult.getList().get(0));
}
@Test
public void testFileConfig() {
// mock 数据
FileConfigDO dbFileConfig = randomFileConfigDO().setMaster(false);
fileConfigMapper.insert(dbFileConfig);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbFileConfig.getId();
// mock 获得 Client
FileClient fileClient = mock(FileClient.class);
when(fileClientFactory.getFileClient(eq(id))).thenReturn(fileClient);
when(fileClient.upload(any(), any())).thenReturn("https://www.iocoder.cn");
// 调用,并断言
assertEquals("https://www.iocoder.cn", fileConfigService.testFileConfig(id));
}
private FileConfigDO randomFileConfigDO() {
return randomPojo(FileConfigDO.class).setStorage(randomEle(FileStorageEnum.values()).getStorage())
.setConfig(new EmptyFileClientConfig());
}
@Data
public static class EmptyFileClientConfig implements FileClientConfig, Serializable {
}
}

View File

@ -26,8 +26,9 @@ spring:
port: 16379 # 端口(单元测试,使用 16379 端口)
database: 0 # 数据库索引
mybatis:
mybatis-plus:
lazy-initialization: true # 单元测试,设置 MyBatis Mapper 延迟加载,加速每个单元测试
type-aliases-package: ${yudao.info.base-package}.module.*.dal.dataobject
--- #################### 定时任务相关配置 ####################
@ -46,4 +47,4 @@ mybatis:
# 芋道配置项,设置当前项目所有自定义的配置
yudao:
info:
base-package: cn.iocoder.yudao.module
base-package: cn.iocoder.yudao

View File

@ -8,3 +8,4 @@ DELETE FROM "infra_api_access_log";
DELETE FROM "infra_file";
DELETE FROM "infra_api_error_log";
DELETE FROM "infra_test_demo";
DELETE FROM "infra_file_config";

View File

@ -16,6 +16,21 @@ CREATE TABLE IF NOT EXISTS "infra_config" (
PRIMARY KEY ("id")
) COMMENT '';
CREATE TABLE IF NOT EXISTS "infra_file_config" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
"name" varchar(63) NOT NULL,
"storage" tinyint NOT NULL,
"remark" varchar(255),
"master" bit(1) NOT NULL,
"config" varchar(4096) NOT NULL,
"creator" varchar(64) DEFAULT '',
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) 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 "infra_file" (
"id" varchar(188) NOT NULL,
"type" varchar(63) DEFAULT NULL,