简化 dict data 的单元测试,将新增、修改、删除涉及的公用方法,单独测试

This commit is contained in:
YunaiV 2021-03-08 00:21:49 +08:00
parent 351d08a2c4
commit 2249d76d46
5 changed files with 122 additions and 148 deletions

View File

@ -28,6 +28,10 @@ public interface BaseMapperX<T> extends BaseMapper<T> {
return selectOne(new QueryWrapper<T>().eq(field, value)); return selectOne(new QueryWrapper<T>().eq(field, value));
} }
default Integer selectCount(String field, Object value) {
return selectCount(new QueryWrapper<T>().eq(field, value));
}
default List<T> selectList() { default List<T> selectList() {
return selectList(new QueryWrapper<>()); return selectList(new QueryWrapper<>());
} }

View File

@ -15,13 +15,13 @@ import java.util.List;
@Mapper @Mapper
public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> { public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> {
default SysDictDataDO selectByDictTypeAndLabel(String dictType, String value) { default SysDictDataDO selectByDictTypeAndValue(String dictType, String value) {
return selectOne(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType) return selectOne(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType)
.eq("value", value)); .eq("value", value));
} }
default int selectCountByDictType(String dictType) { default int selectCountByDictType(String dictType) {
return selectCount(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType)); return selectCount("dict_type", dictType);
} }
default PageResult<SysDictDataDO> selectPage(SysDictDataPageReqVO reqVO) { default PageResult<SysDictDataDO> selectPage(SysDictDataPageReqVO reqVO) {

View File

@ -15,6 +15,7 @@ import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictDataMapper;
import cn.iocoder.dashboard.modules.system.mq.producer.dict.SysDictDataProducer; import cn.iocoder.dashboard.modules.system.mq.producer.dict.SysDictDataProducer;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService; import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableTable; import com.google.common.collect.ImmutableTable;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
@ -200,8 +201,9 @@ public class SysDictDataServiceImpl implements SysDictDataService {
checkDictDataValueUnique(id, dictType, value); checkDictDataValueUnique(id, dictType, value);
} }
private void checkDictDataValueUnique(Long id, String dictType, String label) { @VisibleForTesting
SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndLabel(dictType, label); public void checkDictDataValueUnique(Long id, String dictType, String value) {
SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndValue(dictType, value);
if (dictData == null) { if (dictData == null) {
return; return;
} }
@ -214,7 +216,8 @@ public class SysDictDataServiceImpl implements SysDictDataService {
} }
} }
private void checkDictDataExists(Long id) { @VisibleForTesting
public void checkDictDataExists(Long id) {
if (id == null) { if (id == null) {
return; return;
} }
@ -224,7 +227,8 @@ public class SysDictDataServiceImpl implements SysDictDataService {
} }
} }
private void checkDictTypeValid(String type) { @VisibleForTesting
public void checkDictTypeValid(String type) {
SysDictTypeDO dictType = dictTypeService.getDictType(type); SysDictTypeDO dictType = dictTypeService.getDictType(type);
if (dictType == null) { if (dictType == null) {
throw exception(DICT_TYPE_NOT_EXISTS); throw exception(DICT_TYPE_NOT_EXISTS);

View File

@ -10,6 +10,7 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO;
import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictTypeMapper; import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictTypeMapper;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService; import cn.iocoder.dashboard.modules.system.service.dict.SysDictDataService;
import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService; import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService;
import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -97,7 +98,8 @@ public class SysDictTypeServiceImpl implements SysDictTypeService {
checkDictTypeUnique(id, type); checkDictTypeUnique(id, type);
} }
private void checkDictTypeNameUnique(Long id, String type) { @VisibleForTesting
public void checkDictTypeNameUnique(Long id, String type) {
SysDictTypeDO dictType = dictTypeMapper.selectByName(type); SysDictTypeDO dictType = dictTypeMapper.selectByName(type);
if (dictType == null) { if (dictType == null) {
return; return;
@ -111,7 +113,8 @@ public class SysDictTypeServiceImpl implements SysDictTypeService {
} }
} }
private void checkDictTypeUnique(Long id, String type) { @VisibleForTesting
public void checkDictTypeUnique(Long id, String type) {
SysDictTypeDO dictType = dictTypeMapper.selectByType(type); SysDictTypeDO dictType = dictTypeMapper.selectByType(type);
if (dictType == null) { if (dictType == null) {
return; return;
@ -125,7 +128,8 @@ public class SysDictTypeServiceImpl implements SysDictTypeService {
} }
} }
private SysDictTypeDO checkDictTypeExists(Long id) { @VisibleForTesting
public SysDictTypeDO checkDictTypeExists(Long id) {
if (id == null) { if (id == null) {
return null; return null;
} }

View File

@ -49,6 +49,37 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
@MockBean @MockBean
private SysDictDataProducer dictDataProducer; private SysDictDataProducer dictDataProducer;
/**
* 测试加载到新的字典数据的情况
*/
@Test
@SuppressWarnings("unchecked")
public void testInitLocalCache() {
// mock 数据
SysDictDataDO dictData01 = randomDictDataDO();
dictDataMapper.insert(dictData01);
SysDictDataDO dictData02 = randomDictDataDO();
dictDataMapper.insert(dictData02);
// 调用
dictDataService.initLocalCache();
// 断言 labelDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> labelDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "labelDictDataCache");
assertEquals(2, labelDictDataCache.size());
assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel()));
assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel()));
// 断言 valueDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> valueDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "valueDictDataCache");
assertEquals(2, valueDictDataCache.size());
assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue()));
assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue()));
// 断言 maxUpdateTime 缓存
Date maxUpdateTime = (Date) getFieldValue(dictDataService, "maxUpdateTime");
assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime);
}
@Test @Test
public void testGetDictDataPage() { public void testGetDictDataPage() {
// mock 数据 // mock 数据
@ -125,46 +156,6 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
verify(dictDataProducer, times(1)).sendDictDataRefreshMessage(); verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
} }
@Test
public void testCreateDictData_dictTypeNotExists() {
// 准备参数
SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
o -> o.setStatus(randomCommonStatus()));
// 调用, 并断言异常
assertServiceException(() -> dictDataService.createDictData(reqVO), DICT_TYPE_NOT_EXISTS);
}
@Test
public void testCreateDictData_dictTypeNotEnable() {
// 准备参数
SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
o -> o.setStatus(randomCommonStatus()));
// mock 方法数据类型被禁用
when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(
randomPojo(SysDictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 调用, 并断言异常
assertServiceException(() -> dictDataService.createDictData(reqVO), DICT_TYPE_NOT_ENABLE);
}
@Test
public void testCreateDictData_dictDataValueDuplicate() {
// 准备参数
SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
o -> o.setStatus(randomCommonStatus()));
// mock 方法字典类型
when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
// mock dictData 重复 value 重复
dictDataMapper.insert(randomDictDataDO(o -> {
o.setDictType(reqVO.getDictType());
o.setValue(reqVO.getValue()); // 使用 reqVO value实现重复
}));
// 调用, 并断言异常
assertServiceException(() -> dictDataService.createDictData(reqVO), DICT_DATA_VALUE_DUPLICATE);
}
@Test @Test
public void testUpdateDictData_success() { public void testUpdateDictData_success() {
// mock 数据 // mock 数据
@ -187,101 +178,6 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
verify(dictDataProducer, times(1)).sendDictDataRefreshMessage(); verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
} }
@Test
public void testUpdateDictData_notExists() {
// 准备参数
SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class);
// 调用, 并断言异常
assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_DATA_NOT_EXISTS);
}
/**
* 测试加载到新的字典数据的情况
*/
@Test
@SuppressWarnings("unchecked")
public void testInitLocalCache() {
// mock 数据
SysDictDataDO dictData01 = randomDictDataDO();
dictDataMapper.insert(dictData01);
SysDictDataDO dictData02 = randomDictDataDO();
dictDataMapper.insert(dictData02);
// 调用
dictDataService.initLocalCache();
// 断言 labelDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> labelDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "labelDictDataCache");
assertEquals(2, labelDictDataCache.size());
assertPojoEquals(dictData01, labelDictDataCache.get(dictData01.getDictType(), dictData01.getLabel()));
assertPojoEquals(dictData02, labelDictDataCache.get(dictData02.getDictType(), dictData02.getLabel()));
// 断言 valueDictDataCache 缓存
ImmutableTable<String, String, SysDictDataDO> valueDictDataCache =
(ImmutableTable<String, String, SysDictDataDO>) getFieldValue(dictDataService, "valueDictDataCache");
assertEquals(2, valueDictDataCache.size());
assertPojoEquals(dictData01, valueDictDataCache.get(dictData01.getDictType(), dictData01.getValue()));
assertPojoEquals(dictData02, valueDictDataCache.get(dictData02.getDictType(), dictData02.getValue()));
// 断言 maxUpdateTime 缓存
Date maxUpdateTime = (Date) getFieldValue(dictDataService, "maxUpdateTime");
assertEquals(ObjectUtils.max(dictData01.getUpdateTime(), dictData02.getUpdateTime()), maxUpdateTime);
}
@Test
public void testUpdateDictData_dictTypeNotExists() {
// mock 数据
SysDictDataDO dbDictData = randomDictDataDO();
dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
// 准备参数
SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> {
o.setId(dbDictData.getId()); // 设置更新的 ID
o.setStatus(randomCommonStatus());
});
// 调用, 并断言异常
assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_TYPE_NOT_EXISTS);
}
@Test
public void testUpdateDictData_dictTypeNotEnable() {
// mock 数据
SysDictDataDO dbDictData = randomDictDataDO();
dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
// 准备参数
SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> {
o.setId(dbDictData.getId()); // 设置更新的 ID
o.setStatus(randomCommonStatus());
});
// mock 方法数据类型被禁用
when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(
randomPojo(SysDictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 调用, 并断言异常
assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_TYPE_NOT_ENABLE);
}
@Test
public void testUpdateDictData_dictDataValueDuplicate() {
// mock 数据
SysDictDataDO dbDictData = randomDictDataDO();
dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
// 准备参数
SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> {
o.setId(dbDictData.getId()); // 设置更新的 ID
o.setStatus(randomCommonStatus());
});
// mock 方法字典类型
when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
// mock dictData 重复 value 重复
dictDataMapper.insert(randomDictDataDO(o -> {
o.setDictType(reqVO.getDictType());
o.setValue(reqVO.getValue()); // 使用 reqVO value实现重复
}));
// 调用, 并断言异常
assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_DATA_VALUE_DUPLICATE);
}
@Test @Test
public void testDeleteDictData_success() { public void testDeleteDictData_success() {
// mock 数据 // mock 数据
@ -299,12 +195,78 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
} }
@Test @Test
public void testDeleteDictData_notExists() { public void testCheckDictDataExists_success() {
// 准备参数 // mock 数据
Long id = randomLongId(); SysDictDataDO dbDictData = randomDictDataDO();
dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
// 调用成功
dictDataService.checkDictDataExists(dbDictData.getId());
}
@Test
public void testCheckDictTypeValid_success() {
// mock 方法数据类型被禁用
String type = randomString();
when(dictTypeService.getDictType(eq(type))).thenReturn(randomDictTypeDO(type));
// 调用, 成功
dictDataService.checkDictTypeValid(type);
}
@Test
public void testCheckDictTypeValid_notExists() {
assertServiceException(() -> dictDataService.checkDictTypeValid(randomString()), DICT_TYPE_NOT_EXISTS);
}
@Test
public void testCheckDictTypeValid_notEnable() {
// mock 方法数据类型被禁用
String dictType = randomString();
when(dictTypeService.getDictType(eq(dictType))).thenReturn(
randomPojo(SysDictTypeDO.class, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> dictDataService.deleteDictData(id), DICT_DATA_NOT_EXISTS); assertServiceException(() -> dictDataService.checkDictTypeValid(dictType), DICT_TYPE_NOT_ENABLE);
}
@Test
public void testCheckDictDataValueUnique_success() {
// 调用成功
dictDataService.checkDictDataValueUnique(randomLongId(), randomString(), randomString());
}
@Test
public void testCheckDictDataValueUnique_valueDuplicateForCreate() {
// 准备参数
String dictType = randomString();
String value = randomString();
// mock 数据
dictDataMapper.insert(randomDictDataDO(o -> {
o.setDictType(dictType);
o.setValue(value);
}));
// 调用校验异常
assertServiceException(() -> dictDataService.checkDictDataValueUnique(null, dictType, value),
DICT_DATA_VALUE_DUPLICATE);
}
@Test
public void testCheckDictDataValueUnique_valueDuplicateForUpdate() {
// 准备参数
Long id = randomLongId();
String dictType = randomString();
String value = randomString();
// mock 数据
dictDataMapper.insert(randomDictDataDO(o -> {
o.setDictType(dictType);
o.setValue(value);
}));
// 调用校验异常
assertServiceException(() -> dictDataService.checkDictDataValueUnique(id, dictType, value),
DICT_DATA_VALUE_DUPLICATE);
} }
// ========== 随机对象 ========== // ========== 随机对象 ==========