mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 18:49:06 +08:00 
			
		
		
		
	简化 dict data 的单元测试,将新增、修改、删除涉及的公用方法,单独测试
This commit is contained in:
		| @ -28,6 +28,10 @@ public interface BaseMapperX<T> extends BaseMapper<T> { | ||||
|         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() { | ||||
|         return selectList(new QueryWrapper<>()); | ||||
|     } | ||||
|  | ||||
| @ -15,13 +15,13 @@ import java.util.List; | ||||
| @Mapper | ||||
| 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) | ||||
|                 .eq("value", value)); | ||||
|     } | ||||
|  | ||||
|     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) { | ||||
|  | ||||
| @ -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.service.dict.SysDictDataService; | ||||
| import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService; | ||||
| import com.google.common.annotations.VisibleForTesting; | ||||
| import com.google.common.collect.ImmutableTable; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.springframework.scheduling.annotation.Scheduled; | ||||
| @ -200,8 +201,9 @@ public class SysDictDataServiceImpl implements SysDictDataService { | ||||
|         checkDictDataValueUnique(id, dictType, value); | ||||
|     } | ||||
|  | ||||
|     private void checkDictDataValueUnique(Long id, String dictType, String label) { | ||||
|         SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndLabel(dictType, label); | ||||
|     @VisibleForTesting | ||||
|     public void checkDictDataValueUnique(Long id, String dictType, String value) { | ||||
|         SysDictDataDO dictData = dictDataMapper.selectByDictTypeAndValue(dictType, value); | ||||
|         if (dictData == null) { | ||||
|             return; | ||||
|         } | ||||
| @ -214,7 +216,8 @@ public class SysDictDataServiceImpl implements SysDictDataService { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private void checkDictDataExists(Long id) { | ||||
|     @VisibleForTesting | ||||
|     public void checkDictDataExists(Long id) { | ||||
|         if (id == null) { | ||||
|             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); | ||||
|         if (dictType == null) { | ||||
|             throw exception(DICT_TYPE_NOT_EXISTS); | ||||
|  | ||||
| @ -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.service.dict.SysDictDataService; | ||||
| import cn.iocoder.dashboard.modules.system.service.dict.SysDictTypeService; | ||||
| import com.google.common.annotations.VisibleForTesting; | ||||
| import org.springframework.stereotype.Service; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| @ -97,7 +98,8 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { | ||||
|         checkDictTypeUnique(id, type); | ||||
|     } | ||||
|  | ||||
|     private void checkDictTypeNameUnique(Long id, String type) { | ||||
|     @VisibleForTesting | ||||
|     public void checkDictTypeNameUnique(Long id, String type) { | ||||
|         SysDictTypeDO dictType = dictTypeMapper.selectByName(type); | ||||
|         if (dictType == null) { | ||||
|             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); | ||||
|         if (dictType == null) { | ||||
|             return; | ||||
| @ -125,7 +128,8 @@ public class SysDictTypeServiceImpl implements SysDictTypeService { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private SysDictTypeDO checkDictTypeExists(Long id) { | ||||
|     @VisibleForTesting | ||||
|     public SysDictTypeDO checkDictTypeExists(Long id) { | ||||
|         if (id == null) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
| @ -49,6 +49,37 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest { | ||||
|     @MockBean | ||||
|     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 | ||||
|     public void testGetDictDataPage() { | ||||
|         // mock 数据 | ||||
| @ -125,46 +156,6 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest { | ||||
|         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 | ||||
|     public void testUpdateDictData_success() { | ||||
|         // mock 数据 | ||||
| @ -187,101 +178,6 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest { | ||||
|         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 | ||||
|     public void testDeleteDictData_success() { | ||||
|         // mock 数据 | ||||
| @ -299,12 +195,78 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest { | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testDeleteDictData_notExists() { | ||||
|         // 准备参数 | ||||
|         Long id = randomLongId(); | ||||
|     public void testCheckDictDataExists_success() { | ||||
|         // mock 数据 | ||||
|         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); | ||||
|     } | ||||
|  | ||||
|     // ========== 随机对象 ========== | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV