diff --git a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java index bf086f0a6..c8034e425 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java +++ b/src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java @@ -17,7 +17,7 @@ public class InfConfigBaseVO { @ApiModelProperty(value = "参数分组", required = true, example = "biz") @NotEmpty(message = "参数分组不能为空") - @Size(max = 100, message = "参数名称不能超过50个字符") + @Size(max = 50, message = "参数名称不能超过50个字符") private String group; @ApiModelProperty(value = "参数名称", required = true, example = "数据库名") diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java index 0556d5d65..1cbc7bb0b 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java @@ -30,11 +30,11 @@ import org.springframework.stereotype.Service; import org.springframework.util.Assert; import javax.annotation.Resource; -import java.util.Collections; import java.util.Set; import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; +import static java.util.Collections.singleton; /** * Auth Service 实现类 @@ -155,7 +155,7 @@ public class SysAuthServiceImpl implements SysAuthService { * @return 角色编号数组 */ private Set getUserRoleIds(Long userId) { - return permissionService.listUserRoleIds(userId, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); + return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); } @Override diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java index 56bc60ee7..cfbf205d1 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java @@ -42,7 +42,7 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤 * @return 角色编号集合 */ - Set listUserRoleIds(Long userId, @Nullable Collection roleStatuses); + Set getUserRoleIds(Long userId, @Nullable Collection roleStatuses); /** * 获得角色拥有的菜单编号集合 diff --git a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java index 9f4c87d7b..9f48af9f5 100644 --- a/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java +++ b/src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java @@ -151,7 +151,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { } @Override - public Set listUserRoleIds(Long userId, Collection roleStatuses) { + public Set getUserRoleIds(Long userId, Collection roleStatuses) { List userRoleList = userRoleMapper.selectListByUserId(userId); // 过滤角色状态 if (CollectionUtil.isNotEmpty(roleStatuses)) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index f11c9b889..33f84c5c8 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -24,7 +24,7 @@ spring: mybatis-plus: configuration: map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 global-config: db-config: id-type: AUTO # 自增 ID diff --git a/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceImplTest.java index 3e4b93809..5036353fb 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceImplTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/infra/service/config/InfConfigServiceImplTest.java @@ -11,11 +11,13 @@ import cn.iocoder.dashboard.modules.infra.service.config.impl.InfConfigServiceIm import cn.iocoder.dashboard.util.AssertUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.jdbc.Sql; import javax.annotation.Resource; +import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.CONFIG_KEY_DUPLICATE; +import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigCreateReqVO; +import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigDO; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -34,13 +36,7 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { @Test public void testCreateConfig_success() { // 入参 - InfConfigCreateReqVO reqVO = new InfConfigCreateReqVO(); - reqVO.setGroup("test_group"); - reqVO.setName("test_name"); - reqVO.setValue("test_value"); - reqVO.setSensitive(true); - reqVO.setRemark("test_remark"); - reqVO.setKey("test_key"); + InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); // mock // 调用 @@ -56,17 +52,14 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { } @Test - @Sql(statements = "INSERT INTO `inf_config`(`group`, `type`, `name`, `key`, `value`, `sensitive`) VALUES ('test_group', 1, 'test_name', 'test_key', 'test_value', 1);") public void testCreateConfig_keyDuplicate() { // 入参 - InfConfigCreateReqVO reqVO = new InfConfigCreateReqVO(); - reqVO.setGroup("test_group"); - reqVO.setName("test_name"); - reqVO.setValue("test_value"); - reqVO.setSensitive(true); - reqVO.setRemark("test_remark"); - reqVO.setKey("test_key"); - // mock + InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); + // mock 数据 + configMapper.insert(randomInfConfigDO(o -> { + o.setKey(reqVO.getKey()); // @Sql:插入一条重复的 key + o.setType(randomEle(InfConfigTypeEnum.values()).getType()); + })); // 调用 ServiceException serviceException = assertThrows(ServiceException.class, () -> configService.createConfig(reqVO)); diff --git a/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java b/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java index e8d00df11..1b39876c2 100644 --- a/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java +++ b/src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java @@ -1,19 +1,23 @@ package cn.iocoder.dashboard.modules.system.service.auth; import cn.iocoder.dashboard.BaseSpringBootUnitTest; +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; import cn.iocoder.dashboard.framework.security.core.LoginUser; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.dashboard.modules.system.service.auth.impl.SysAuthServiceImpl; +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import cn.iocoder.dashboard.util.AssertUtils; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import javax.annotation.Resource; +import java.util.Set; -import static cn.iocoder.dashboard.util.RandomUtils.randomString; -import static cn.iocoder.dashboard.util.RandomUtils.randomUserDO; -import static org.junit.jupiter.api.Assertions.assertNull; +import static cn.iocoder.dashboard.util.RandomUtils.*; +import static java.util.Collections.singleton; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -24,13 +28,15 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { @MockBean private SysUserService userService; + @MockBean + private SysPermissionService permissionService; @Test public void testLoadUserByUsername_success() { // 准备参数 String username = randomString(); // mock 方法 - SysUserDO user = randomUserDO(); + SysUserDO user = randomUserDO(o -> o.setUsername(username)); when(userService.getUserByUserName(eq(username))).thenReturn(user); // 调用 @@ -40,4 +46,47 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的 } + @Test + public void testLoadUserByUsername_userNotFound() { + // 准备参数 + String username = randomString(); + // mock 方法 + + // 调用, 并断言异常 + assertThrows(UsernameNotFoundException.class, // 抛出 UsernameNotFoundException 异常 + () -> authService.loadUserByUsername(username), + username); // 异常提示为 username + } + + @Test + public void testMockLogin_success() { + // 准备参数 + Long userId = randomLong(); + // mock 方法 01 + SysUserDO user = randomUserDO(o -> o.setId(userId)); + when(userService.getUser(eq(userId))).thenReturn(user); + // mock 方法 02 + Set roleIds = randomSet(Long.class); + when(permissionService.getUserRoleIds(eq(userId), eq(singleton(CommonStatusEnum.ENABLE.getStatus())))) + .thenReturn(roleIds); + + // 调用 + LoginUser loginUser = authService.mockLogin(userId); + // 断言 + AssertUtils.assertEquals(user, loginUser, "updateTime"); + assertEquals(roleIds, loginUser.getRoleIds()); + } + + @Test + public void testMockLogin_userNotFound() { + // 准备参数 + Long userId = randomLong(); + // mock 方法 + + // 调用, 并断言异常 + assertThrows(UsernameNotFoundException.class, // 抛出 UsernameNotFoundException 异常 + () -> authService.mockLogin(userId), + String.valueOf(userId)); // 异常提示为 userId + } + } diff --git a/src/test/java/cn/iocoder/dashboard/util/RandomUtils.java b/src/test/java/cn/iocoder/dashboard/util/RandomUtils.java index 4b39f080d..f0ff48193 100644 --- a/src/test/java/cn/iocoder/dashboard/util/RandomUtils.java +++ b/src/test/java/cn/iocoder/dashboard/util/RandomUtils.java @@ -2,13 +2,18 @@ package cn.iocoder.dashboard.util; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.RandomUtil; +import cn.iocoder.dashboard.modules.infra.controller.config.vo.InfConfigCreateReqVO; +import cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO; import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; import uk.co.jemos.podam.api.PodamFactory; import uk.co.jemos.podam.api.PodamFactoryImpl; import java.util.Arrays; import java.util.Date; +import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * 随机工具类 @@ -21,8 +26,24 @@ public class RandomUtils { private static final int RANDOM_DATE_MAX = 30; + private static final int RANDOM_COLLECTION_LENGTH = 5; + private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); + static { + // 字符串 + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class, + (dataProviderStrategy, attributeMetadata, map) -> randomString()); + // Boolean + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { + // 如果是 deleted 的字段,返回非删除 + if (attributeMetadata.getAttributeName().equals("deleted")) { + return false; + } + return RandomUtil.randomBoolean(); + }); + } + public static String randomString() { return RandomUtil.randomString(RANDOM_STRING_LENGTH); } @@ -43,11 +64,26 @@ public class RandomUtils { return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); } + public static Set randomSet(Class clazz) { + return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(0, RANDOM_DATE_MAX)) + .map(i -> randomPojo(clazz)).collect(Collectors.toSet()); + } + @SafeVarargs public static SysUserDO randomUserDO(Consumer... consumers) { return randomPojo(SysUserDO.class, consumers); } + @SafeVarargs + public static InfConfigCreateReqVO randomInfConfigCreateReqVO(Consumer... consumers) { + return randomPojo(InfConfigCreateReqVO.class, consumers); + } + + @SafeVarargs + public static InfConfigDO randomInfConfigDO(Consumer... consumers) { + return randomPojo(InfConfigDO.class, consumers); + } + @SafeVarargs private static T randomPojo(Class clazz, Consumer... consumers) { T pojo = PODAM_FACTORY.manufacturePojo(clazz); diff --git a/src/test/resources/application-unit-test.yaml b/src/test/resources/application-unit-test.yaml index e402c29e8..b8406322c 100644 --- a/src/test/resources/application-unit-test.yaml +++ b/src/test/resources/application-unit-test.yaml @@ -10,6 +10,8 @@ spring: - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration # 单元测试,禁用 SpringSecurity - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 单元测试,禁用 Quartz - com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration # 单元测试,禁用 Lock4j 分布式锁 + - org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration # 单元测试,禁用 Scheduler 定时任务 + - org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration # 项目没有使用 Spring Data,所以禁用配置类,加速启动 # Swagger 接口文档的自动配置(单元测试,禁用 Swagger) springfox: