完善 dict data 的单元测试

pull/2/head
YunaiV 2021-03-07 22:36:08 +08:00
parent cafb72b582
commit 113e34b279
4 changed files with 150 additions and 22 deletions

View File

@ -15,9 +15,9 @@ import java.util.List;
@Mapper
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)
.eq("label", label));
.eq("value", value));
}
default int selectCountByDictType(String dictType) {

View File

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

View File

@ -2,6 +2,8 @@ package cn.iocoder.dashboard.util.collection;
import cn.hutool.core.util.ArrayUtil;
import java.util.function.Consumer;
/**
* Array
*
@ -18,11 +20,11 @@ public class ArrayUtils {
* @return
*/
@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) {
return newElements;
}
T[] result = ArrayUtil.newArray(object.getClass(), 1 + newElements.length);
Consumer<T>[] result = ArrayUtil.newArray(Consumer.class, 1 + newElements.length);
result[0] = object;
System.arraycopy(newElements, 0, result, 1, newElements.length);
return result;

View File

@ -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.mq.producer.dict.SysDictDataProducer;
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 org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import javax.annotation.Resource;
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.assertServiceException;
import static cn.iocoder.dashboard.util.RandomUtils.*;
@ -107,8 +109,7 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
SysDictDataCreateReqVO reqVO = randomPojo(SysDictDataCreateReqVO.class,
o -> o.setStatus(randomCommonStatus()));
// 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);
@ -121,21 +122,66 @@ 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 数据
SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class);
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()));
// 调用
dictDataService.updateDictData(reqVO);
// 校验是否更新正确
SysDictDataDO dictData = dictDataMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, dictData);
// 校验调用
verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
}
@Test
@ -147,18 +193,75 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
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
public void testDeleteDictData_success() {
// mock 数据
SysDictDataDO dbDictData = randomPojo(SysDictDataDO.class);
SysDictDataDO dbDictData = randomDictDataDO();
dictDataMapper.insert(dbDictData);// @Sql: 先插入出一条存在的数据
// 准备参数
Long id = dbDictData.getId();
// 调用
dictDataService.deleteDictData(id);
// 校验数据不存在了
assertNull(dictDataMapper.selectById(id));
// 校验数据不存在了
assertNull(dictDataMapper.selectById(id));
// 校验调用
verify(dictDataProducer, times(1)).sendDictDataRefreshMessage();
}
@Test
@ -170,4 +273,27 @@ public class SysDictDataServiceTest extends BaseSpringBootUnitTest {
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 是开启
});
}
}