Эх сурвалжийг харах

完善 dict data 的单元测试

YunaiV 4 жил өмнө
parent
commit
113e34b279

+ 2 - 2
src/main/java/cn/iocoder/dashboard/modules/system/dal/mysql/dict/SysDictDataMapper.java

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

+ 11 - 11
src/main/java/cn/iocoder/dashboard/modules/system/service/dict/impl/SysDictDataServiceImpl.java

@@ -2,7 +2,6 @@ package cn.iocoder.dashboard.modules.system.service.dict.impl;
 
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
 import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
-import cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.common.pojo.PageResult;
 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.dashboard.framework.mybatis.core.dataobject.BaseDO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataCreateReqVO;
@@ -10,9 +9,9 @@ import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataEx
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataPageReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.controller.dict.vo.data.SysDictDataUpdateReqVO;
 import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert;
 import cn.iocoder.dashboard.modules.system.convert.dict.SysDictDataConvert;
-import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictDataMapper;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictDataDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictDataDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO;
 import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO;
+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;
@@ -28,6 +27,7 @@ import java.util.Comparator;
 import java.util.Date;
 import java.util.Date;
 import java.util.List;
 import java.util.List;
 
 
+import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
 
 
 /**
 /**
@@ -156,7 +156,7 @@ public class SysDictDataServiceImpl implements SysDictDataService {
     @Override
     @Override
     public Long createDictData(SysDictDataCreateReqVO reqVO) {
     public Long createDictData(SysDictDataCreateReqVO reqVO) {
         // 校验正确性
         // 校验正确性
-        this.checkCreateOrUpdate(null, reqVO.getLabel(), reqVO.getDictType());
+        this.checkCreateOrUpdate(null, reqVO.getValue(), reqVO.getDictType());
         // 插入字典类型
         // 插入字典类型
         SysDictDataDO dictData = SysDictDataConvert.INSTANCE.convert(reqVO);
         SysDictDataDO dictData = SysDictDataConvert.INSTANCE.convert(reqVO);
         dictDataMapper.insert(dictData);
         dictDataMapper.insert(dictData);
@@ -168,7 +168,7 @@ public class SysDictDataServiceImpl implements SysDictDataService {
     @Override
     @Override
     public void updateDictData(SysDictDataUpdateReqVO reqVO) {
     public void updateDictData(SysDictDataUpdateReqVO reqVO) {
         // 校验正确性
         // 校验正确性
-        this.checkCreateOrUpdate(reqVO.getId(), reqVO.getLabel(), reqVO.getDictType());
+        this.checkCreateOrUpdate(reqVO.getId(), reqVO.getValue(), reqVO.getDictType());
         // 更新字典类型
         // 更新字典类型
         SysDictDataDO updateObj = SysDictDataConvert.INSTANCE.convert(reqVO);
         SysDictDataDO updateObj = SysDictDataConvert.INSTANCE.convert(reqVO);
         dictDataMapper.updateById(updateObj);
         dictDataMapper.updateById(updateObj);
@@ -191,13 +191,13 @@ public class SysDictDataServiceImpl implements SysDictDataService {
         return dictDataMapper.selectCountByDictType(dictType);
         return dictDataMapper.selectCountByDictType(dictType);
     }
     }
 
 
-    private void checkCreateOrUpdate(Long id, String label, String dictType) {
+    private void checkCreateOrUpdate(Long id, String value, String dictType) {
         // 校验自己存在
         // 校验自己存在
         checkDictDataExists(id);
         checkDictDataExists(id);
         // 校验字典类型有效
         // 校验字典类型有效
         checkDictTypeValid(dictType);
         checkDictTypeValid(dictType);
         // 校验字典数据的值的唯一性
         // 校验字典数据的值的唯一性
-        checkDictDataValueUnique(id, dictType, label);
+        checkDictDataValueUnique(id, dictType, value);
     }
     }
 
 
     private void checkDictDataValueUnique(Long id, String dictType, String label) {
     private void checkDictDataValueUnique(Long id, String dictType, String label) {
@@ -207,10 +207,10 @@ public class SysDictDataServiceImpl implements SysDictDataService {
         }
         }
         // 如果 id 为空,说明不用比较是否为相同 id 的字典数据
         // 如果 id 为空,说明不用比较是否为相同 id 的字典数据
         if (id == null) {
         if (id == null) {
-            throw ServiceExceptionUtil.exception(DICT_DATA_VALUE_DUPLICATE);
+            throw exception(DICT_DATA_VALUE_DUPLICATE);
         }
         }
         if (!dictData.getId().equals(id)) {
         if (!dictData.getId().equals(id)) {
-            throw ServiceExceptionUtil.exception(DICT_DATA_VALUE_DUPLICATE);
+            throw exception(DICT_DATA_VALUE_DUPLICATE);
         }
         }
     }
     }
 
 
@@ -220,17 +220,17 @@ public class SysDictDataServiceImpl implements SysDictDataService {
         }
         }
         SysDictDataDO dictData = dictDataMapper.selectById(id);
         SysDictDataDO dictData = dictDataMapper.selectById(id);
         if (dictData == null) {
         if (dictData == null) {
-            throw ServiceExceptionUtil.exception(DICT_DATA_NOT_EXISTS);
+            throw exception(DICT_DATA_NOT_EXISTS);
         }
         }
     }
     }
 
 
     private void checkDictTypeValid(String type) {
     private void checkDictTypeValid(String type) {
         SysDictTypeDO dictType = dictTypeService.getDictType(type);
         SysDictTypeDO dictType = dictTypeService.getDictType(type);
         if (dictType == null) {
         if (dictType == null) {
-            throw ServiceExceptionUtil.exception(DICT_TYPE_NOT_EXISTS);
+            throw exception(DICT_TYPE_NOT_EXISTS);
         }
         }
         if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) {
         if (!CommonStatusEnum.ENABLE.getStatus().equals(dictType.getStatus())) {
-            throw ServiceExceptionUtil.exception(DICT_TYPE_NOT_ENABLE);
+            throw exception(DICT_TYPE_NOT_ENABLE);
         }
         }
     }
     }
 
 

+ 4 - 2
src/main/java/cn/iocoder/dashboard/util/collection/ArrayUtils.java

@@ -2,6 +2,8 @@ package cn.iocoder.dashboard.util.collection;
 
 
 import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.ArrayUtil;
 
 
+import java.util.function.Consumer;
+
 /**
 /**
  * Array 工具类
  * Array 工具类
  *
  *
@@ -18,11 +20,11 @@ public class ArrayUtils {
      * @return 结果数组
      * @return 结果数组
      */
      */
     @SafeVarargs
     @SafeVarargs
-    public static <T> T[] append(T object, T... newElements) {
+    public static <T> Consumer<T>[] append(Consumer<T> object, Consumer<T>... newElements) {
         if (object == null) {
         if (object == null) {
             return newElements;
             return newElements;
         }
         }
-        T[] result = ArrayUtil.newArray(object.getClass(), 1 + newElements.length);
+        Consumer<T>[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length);
         result[0] = object;
         result[0] = object;
         System.arraycopy(newElements, 0, result, 1, newElements.length);
         System.arraycopy(newElements, 0, result, 1, newElements.length);
         return result;
         return result;

+ 133 - 7
src/test/java/cn/iocoder/dashboard/modules/system/service/dict/SysDictDataServiceTest.java

@@ -12,14 +12,16 @@ import cn.iocoder.dashboard.modules.system.dal.dataobject.dict.SysDictTypeDO;
 import cn.iocoder.dashboard.modules.system.dal.mysql.dict.SysDictDataMapper;
 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.impl.SysDictDataServiceImpl;
 import cn.iocoder.dashboard.modules.system.service.dict.impl.SysDictDataServiceImpl;
+import cn.iocoder.dashboard.util.collection.ArrayUtils;
 import cn.iocoder.dashboard.util.object.ObjectUtils;
 import cn.iocoder.dashboard.util.object.ObjectUtils;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.boot.test.mock.mockito.MockBean;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
 import java.util.List;
 import java.util.List;
+import java.util.function.Consumer;
 
 
-import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.DICT_DATA_NOT_EXISTS;
+import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
 import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.dashboard.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
 import static cn.iocoder.dashboard.util.AssertUtils.assertServiceException;
 import static cn.iocoder.dashboard.util.RandomUtils.*;
 import static cn.iocoder.dashboard.util.RandomUtils.*;
@@ -107,8 +109,7 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
         SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
         SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
                 o -> o.setStatus(randomCommonStatus()));
                 o -> o.setStatus(randomCommonStatus()));
         // mock 方法
         // mock 方法
-        when(dictTypeService.getDictType(eq(reqVO.getDictType())))
-                .thenReturn(randomPojo(SysDictTypeDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
+        when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
 
 
         // 调用
         // 调用
         Long dictDataId = dictDataService.createDictData(reqVO);
         Long dictDataId = dictDataService.createDictData(reqVO);
@@ -121,21 +122,66 @@ 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 数据
-        SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class);
+        SysDictDataDO dbDictData = randomDictDataDO();
         dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
         dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
         // 准备参数
         // 准备参数
         SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> {
         SysDictDataUpdateReqVO reqVO = randomPojo(SysDictDataUpdateReqVO.class, o -> {
             o.setId(dbDictData.getId()); // 设置更新的 ID
             o.setId(dbDictData.getId()); // 设置更新的 ID
+            o.setStatus(randomCommonStatus());
         });
         });
+        // mock 方法,字典类型
+        when(dictTypeService.getDictType(eq(reqVO.getDictType()))).thenReturn(randomDictTypeDO(reqVO.getDictType()));
 
 
         // 调用
         // 调用
         dictDataService.updateDictData(reqVO);
         dictDataService.updateDictData(reqVO);
         // 校验是否更新正确
         // 校验是否更新正确
         SysDictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的
         SysDictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的
         assertPojoEquals(reqVO, dictData);
         assertPojoEquals(reqVO, dictData);
+        // 校验调用
+        verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
     }
     }
 
 
     @Test
     @Test
@@ -147,18 +193,75 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
         assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_DATA_NOT_EXISTS);
         assertServiceException(() -> dictDataService.updateDictData(reqVO), DICT_DATA_NOT_EXISTS);
     }
     }
 
 
+    @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 数据
-        SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class);
+        SysDictDataDO dbDictData = randomDictDataDO();
         dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
         dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
         // 准备参数
         // 准备参数
         Long id = dbDictData.getId();
         Long id = dbDictData.getId();
 
 
         // 调用
         // 调用
         dictDataService.deleteDictData(id);
         dictDataService.deleteDictData(id);
-       // 校验数据不存在了
-       assertNull(dictDataMapper.selectById(id));
+        // 校验数据不存在了
+        assertNull(dictDataMapper.selectById(id));
+        // 校验调用
+        verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
     }
     }
 
 
     @Test
     @Test
@@ -170,4 +273,27 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
         assertServiceException(() -> dictDataService.deleteDictData(id), DICT_DATA_NOT_EXISTS);
         assertServiceException(() -> dictDataService.deleteDictData(id), DICT_DATA_NOT_EXISTS);
     }
     }
 
 
+    // ========== 随机对象 ==========
+
+    @SafeVarargs
+    private static SysDictDataDO randomDictDataDO(Consumer<SysDictDataDO>... consumers) {
+        Consumer<SysDictDataDO> consumer = (o) -> {
+            o.setStatus(randomCommonStatus()); // 保证 status 的范围
+        };
+        return randomPojo(SysDictDataDO.class, ArrayUtils.append(consumer, consumers));
+    }
+
+    /**
+     * 生成一个有效的字典类型
+     *
+     * @param type 字典类型
+     * @return SysDictTypeDO 对象
+     */
+    private static SysDictTypeDO randomDictTypeDO(String type) {
+        return randomPojo(SysDictTypeDO.class, o -> {
+            o.setType(type);
+            o.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 保证 status 是开启
+        });
+    }
+
 }
 }