Commit fcad34a5bf602e0179d8e28aa5b09c23a64c39e4
1 parent
632be011
inf_config Service 的单元测试
Showing
9 changed files
with
107 additions
and
27 deletions
src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java
| ... | ... | @@ -17,7 +17,7 @@ public class InfConfigBaseVO { |
| 17 | 17 | |
| 18 | 18 | @ApiModelProperty(value = "参数分组", required = true, example = "biz") |
| 19 | 19 | @NotEmpty(message = "参数分组不能为空") |
| 20 | - @Size(max = 100, message = "参数名称不能超过50个字符") | |
| 20 | + @Size(max = 50, message = "参数名称不能超过50个字符") | |
| 21 | 21 | private String group; |
| 22 | 22 | |
| 23 | 23 | @ApiModelProperty(value = "参数名称", required = true, example = "数据库名") | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/auth/impl/SysAuthServiceImpl.java
| ... | ... | @@ -30,11 +30,11 @@ import org.springframework.stereotype.Service; |
| 30 | 30 | import org.springframework.util.Assert; |
| 31 | 31 | |
| 32 | 32 | import javax.annotation.Resource; |
| 33 | -import java.util.Collections; | |
| 34 | 33 | import java.util.Set; |
| 35 | 34 | |
| 36 | 35 | import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; |
| 37 | 36 | import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; |
| 37 | +import static java.util.Collections.singleton; | |
| 38 | 38 | |
| 39 | 39 | /** |
| 40 | 40 | * Auth Service 实现类 |
| ... | ... | @@ -155,7 +155,7 @@ public class SysAuthServiceImpl implements SysAuthService { |
| 155 | 155 | * @return 角色编号数组 |
| 156 | 156 | */ |
| 157 | 157 | private Set<Long> getUserRoleIds(Long userId) { |
| 158 | - return permissionService.listUserRoleIds(userId, Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); | |
| 158 | + return permissionService.getUserRoleIds(userId, singleton(CommonStatusEnum.ENABLE.getStatus())); | |
| 159 | 159 | } |
| 160 | 160 | |
| 161 | 161 | @Override | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java
| ... | ... | @@ -42,7 +42,7 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService |
| 42 | 42 | * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤 |
| 43 | 43 | * @return 角色编号集合 |
| 44 | 44 | */ |
| 45 | - Set<Long> listUserRoleIds(Long userId, @Nullable Collection<Integer> roleStatuses); | |
| 45 | + Set<Long> getUserRoleIds(Long userId, @Nullable Collection<Integer> roleStatuses); | |
| 46 | 46 | |
| 47 | 47 | /** |
| 48 | 48 | * 获得角色拥有的菜单编号集合 | ... | ... |
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/impl/SysPermissionServiceImpl.java
| ... | ... | @@ -151,7 +151,7 @@ public class SysPermissionServiceImpl implements SysPermissionService { |
| 151 | 151 | } |
| 152 | 152 | |
| 153 | 153 | @Override |
| 154 | - public Set<Long> listUserRoleIds(Long userId, Collection<Integer> roleStatuses) { | |
| 154 | + public Set<Long> getUserRoleIds(Long userId, Collection<Integer> roleStatuses) { | |
| 155 | 155 | List<SysUserRoleDO> userRoleList = userRoleMapper.selectListByUserId(userId); |
| 156 | 156 | // 过滤角色状态 |
| 157 | 157 | if (CollectionUtil.isNotEmpty(roleStatuses)) { | ... | ... |
src/main/resources/application.yaml
| ... | ... | @@ -24,7 +24,7 @@ spring: |
| 24 | 24 | mybatis-plus: |
| 25 | 25 | configuration: |
| 26 | 26 | map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 |
| 27 | -# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 | |
| 27 | + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 | |
| 28 | 28 | global-config: |
| 29 | 29 | db-config: |
| 30 | 30 | id-type: AUTO # 自增 ID | ... | ... |
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 |
| 11 | 11 | import cn.iocoder.dashboard.util.AssertUtils; |
| 12 | 12 | import org.junit.jupiter.api.Test; |
| 13 | 13 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 14 | -import org.springframework.test.context.jdbc.Sql; | |
| 15 | 14 | |
| 16 | 15 | import javax.annotation.Resource; |
| 17 | 16 | |
| 17 | +import static cn.hutool.core.util.RandomUtil.randomEle; | |
| 18 | 18 | import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.CONFIG_KEY_DUPLICATE; |
| 19 | +import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigCreateReqVO; | |
| 20 | +import static cn.iocoder.dashboard.util.RandomUtils.randomInfConfigDO; | |
| 19 | 21 | import static org.junit.jupiter.api.Assertions.*; |
| 20 | 22 | import static org.mockito.Mockito.times; |
| 21 | 23 | import static org.mockito.Mockito.verify; |
| ... | ... | @@ -34,13 +36,7 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { |
| 34 | 36 | @Test |
| 35 | 37 | public void testCreateConfig_success() { |
| 36 | 38 | // 入参 |
| 37 | - InfConfigCreateReqVO reqVO = new InfConfigCreateReqVO(); | |
| 38 | - reqVO.setGroup("test_group"); | |
| 39 | - reqVO.setName("test_name"); | |
| 40 | - reqVO.setValue("test_value"); | |
| 41 | - reqVO.setSensitive(true); | |
| 42 | - reqVO.setRemark("test_remark"); | |
| 43 | - reqVO.setKey("test_key"); | |
| 39 | + InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); | |
| 44 | 40 | // mock |
| 45 | 41 | |
| 46 | 42 | // 调用 |
| ... | ... | @@ -56,17 +52,14 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { |
| 56 | 52 | } |
| 57 | 53 | |
| 58 | 54 | @Test |
| 59 | - @Sql(statements = "INSERT INTO `inf_config`(`group`, `type`, `name`, `key`, `value`, `sensitive`) VALUES ('test_group', 1, 'test_name', 'test_key', 'test_value', 1);") | |
| 60 | 55 | public void testCreateConfig_keyDuplicate() { |
| 61 | 56 | // 入参 |
| 62 | - InfConfigCreateReqVO reqVO = new InfConfigCreateReqVO(); | |
| 63 | - reqVO.setGroup("test_group"); | |
| 64 | - reqVO.setName("test_name"); | |
| 65 | - reqVO.setValue("test_value"); | |
| 66 | - reqVO.setSensitive(true); | |
| 67 | - reqVO.setRemark("test_remark"); | |
| 68 | - reqVO.setKey("test_key"); | |
| 69 | - // mock | |
| 57 | + InfConfigCreateReqVO reqVO = randomInfConfigCreateReqVO(); | |
| 58 | + // mock 数据 | |
| 59 | + configMapper.insert(randomInfConfigDO(o -> { | |
| 60 | + o.setKey(reqVO.getKey()); // @Sql:插入一条重复的 key | |
| 61 | + o.setType(randomEle(InfConfigTypeEnum.values()).getType()); | |
| 62 | + })); | |
| 70 | 63 | |
| 71 | 64 | // 调用 |
| 72 | 65 | ServiceException serviceException = assertThrows(ServiceException.class, () -> configService.createConfig(reqVO)); | ... | ... |
src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java
| 1 | 1 | package cn.iocoder.dashboard.modules.system.service.auth; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.dashboard.BaseSpringBootUnitTest; |
| 4 | +import cn.iocoder.dashboard.common.enums.CommonStatusEnum; | |
| 4 | 5 | import cn.iocoder.dashboard.framework.security.core.LoginUser; |
| 5 | 6 | import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; |
| 6 | 7 | import cn.iocoder.dashboard.modules.system.service.auth.impl.SysAuthServiceImpl; |
| 8 | +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService; | |
| 7 | 9 | import cn.iocoder.dashboard.modules.system.service.user.SysUserService; |
| 8 | 10 | import cn.iocoder.dashboard.util.AssertUtils; |
| 9 | 11 | import org.junit.jupiter.api.Test; |
| 10 | 12 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 13 | +import org.springframework.security.core.userdetails.UsernameNotFoundException; | |
| 11 | 14 | |
| 12 | 15 | import javax.annotation.Resource; |
| 16 | +import java.util.Set; | |
| 13 | 17 | |
| 14 | -import static cn.iocoder.dashboard.util.RandomUtils.randomString; | |
| 15 | -import static cn.iocoder.dashboard.util.RandomUtils.randomUserDO; | |
| 16 | -import static org.junit.jupiter.api.Assertions.assertNull; | |
| 18 | +import static cn.iocoder.dashboard.util.RandomUtils.*; | |
| 19 | +import static java.util.Collections.singleton; | |
| 20 | +import static org.junit.jupiter.api.Assertions.*; | |
| 17 | 21 | import static org.mockito.ArgumentMatchers.eq; |
| 18 | 22 | import static org.mockito.Mockito.when; |
| 19 | 23 | |
| ... | ... | @@ -24,13 +28,15 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { |
| 24 | 28 | |
| 25 | 29 | @MockBean |
| 26 | 30 | private SysUserService userService; |
| 31 | + @MockBean | |
| 32 | + private SysPermissionService permissionService; | |
| 27 | 33 | |
| 28 | 34 | @Test |
| 29 | 35 | public void testLoadUserByUsername_success() { |
| 30 | 36 | // 准备参数 |
| 31 | 37 | String username = randomString(); |
| 32 | 38 | // mock 方法 |
| 33 | - SysUserDO user = randomUserDO(); | |
| 39 | + SysUserDO user = randomUserDO(o -> o.setUsername(username)); | |
| 34 | 40 | when(userService.getUserByUserName(eq(username))).thenReturn(user); |
| 35 | 41 | |
| 36 | 42 | // 调用 |
| ... | ... | @@ -40,4 +46,47 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { |
| 40 | 46 | assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的 |
| 41 | 47 | } |
| 42 | 48 | |
| 49 | + @Test | |
| 50 | + public void testLoadUserByUsername_userNotFound() { | |
| 51 | + // 准备参数 | |
| 52 | + String username = randomString(); | |
| 53 | + // mock 方法 | |
| 54 | + | |
| 55 | + // 调用, 并断言异常 | |
| 56 | + assertThrows(UsernameNotFoundException.class, // 抛出 UsernameNotFoundException 异常 | |
| 57 | + () -> authService.loadUserByUsername(username), | |
| 58 | + username); // 异常提示为 username | |
| 59 | + } | |
| 60 | + | |
| 61 | + @Test | |
| 62 | + public void testMockLogin_success() { | |
| 63 | + // 准备参数 | |
| 64 | + Long userId = randomLong(); | |
| 65 | + // mock 方法 01 | |
| 66 | + SysUserDO user = randomUserDO(o -> o.setId(userId)); | |
| 67 | + when(userService.getUser(eq(userId))).thenReturn(user); | |
| 68 | + // mock 方法 02 | |
| 69 | + Set<Long> roleIds = randomSet(Long.class); | |
| 70 | + when(permissionService.getUserRoleIds(eq(userId), eq(singleton(CommonStatusEnum.ENABLE.getStatus())))) | |
| 71 | + .thenReturn(roleIds); | |
| 72 | + | |
| 73 | + // 调用 | |
| 74 | + LoginUser loginUser = authService.mockLogin(userId); | |
| 75 | + // 断言 | |
| 76 | + AssertUtils.assertEquals(user, loginUser, "updateTime"); | |
| 77 | + assertEquals(roleIds, loginUser.getRoleIds()); | |
| 78 | + } | |
| 79 | + | |
| 80 | + @Test | |
| 81 | + public void testMockLogin_userNotFound() { | |
| 82 | + // 准备参数 | |
| 83 | + Long userId = randomLong(); | |
| 84 | + // mock 方法 | |
| 85 | + | |
| 86 | + // 调用, 并断言异常 | |
| 87 | + assertThrows(UsernameNotFoundException.class, // 抛出 UsernameNotFoundException 异常 | |
| 88 | + () -> authService.mockLogin(userId), | |
| 89 | + String.valueOf(userId)); // 异常提示为 userId | |
| 90 | + } | |
| 91 | + | |
| 43 | 92 | } | ... | ... |
src/test/java/cn/iocoder/dashboard/util/RandomUtils.java
| ... | ... | @@ -2,13 +2,18 @@ package cn.iocoder.dashboard.util; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.util.ArrayUtil; |
| 4 | 4 | import cn.hutool.core.util.RandomUtil; |
| 5 | +import cn.iocoder.dashboard.modules.infra.controller.config.vo.InfConfigCreateReqVO; | |
| 6 | +import cn.iocoder.dashboard.modules.infra.dal.dataobject.config.InfConfigDO; | |
| 5 | 7 | import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; |
| 6 | 8 | import uk.co.jemos.podam.api.PodamFactory; |
| 7 | 9 | import uk.co.jemos.podam.api.PodamFactoryImpl; |
| 8 | 10 | |
| 9 | 11 | import java.util.Arrays; |
| 10 | 12 | import java.util.Date; |
| 13 | +import java.util.Set; | |
| 11 | 14 | import java.util.function.Consumer; |
| 15 | +import java.util.stream.Collectors; | |
| 16 | +import java.util.stream.Stream; | |
| 12 | 17 | |
| 13 | 18 | /** |
| 14 | 19 | * 随机工具类 |
| ... | ... | @@ -21,8 +26,24 @@ public class RandomUtils { |
| 21 | 26 | |
| 22 | 27 | private static final int RANDOM_DATE_MAX = 30; |
| 23 | 28 | |
| 29 | + private static final int RANDOM_COLLECTION_LENGTH = 5; | |
| 30 | + | |
| 24 | 31 | private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); |
| 25 | 32 | |
| 33 | + static { | |
| 34 | + // 字符串 | |
| 35 | + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(String.class, | |
| 36 | + (dataProviderStrategy, attributeMetadata, map) -> randomString()); | |
| 37 | + // Boolean | |
| 38 | + PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(Boolean.class, (dataProviderStrategy, attributeMetadata, map) -> { | |
| 39 | + // 如果是 deleted 的字段,返回非删除 | |
| 40 | + if (attributeMetadata.getAttributeName().equals("deleted")) { | |
| 41 | + return false; | |
| 42 | + } | |
| 43 | + return RandomUtil.randomBoolean(); | |
| 44 | + }); | |
| 45 | + } | |
| 46 | + | |
| 26 | 47 | public static String randomString() { |
| 27 | 48 | return RandomUtil.randomString(RANDOM_STRING_LENGTH); |
| 28 | 49 | } |
| ... | ... | @@ -43,12 +64,27 @@ public class RandomUtils { |
| 43 | 64 | return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); |
| 44 | 65 | } |
| 45 | 66 | |
| 67 | + public static <T> Set<T> randomSet(Class<T> clazz) { | |
| 68 | + return Stream.iterate(0, i -> i).limit(RandomUtil.randomInt(0, RANDOM_DATE_MAX)) | |
| 69 | + .map(i -> randomPojo(clazz)).collect(Collectors.toSet()); | |
| 70 | + } | |
| 71 | + | |
| 46 | 72 | @SafeVarargs |
| 47 | 73 | public static SysUserDO randomUserDO(Consumer<SysUserDO>... consumers) { |
| 48 | 74 | return randomPojo(SysUserDO.class, consumers); |
| 49 | 75 | } |
| 50 | 76 | |
| 51 | 77 | @SafeVarargs |
| 78 | + public static InfConfigCreateReqVO randomInfConfigCreateReqVO(Consumer<InfConfigCreateReqVO>... consumers) { | |
| 79 | + return randomPojo(InfConfigCreateReqVO.class, consumers); | |
| 80 | + } | |
| 81 | + | |
| 82 | + @SafeVarargs | |
| 83 | + public static InfConfigDO randomInfConfigDO(Consumer<InfConfigDO>... consumers) { | |
| 84 | + return randomPojo(InfConfigDO.class, consumers); | |
| 85 | + } | |
| 86 | + | |
| 87 | + @SafeVarargs | |
| 52 | 88 | private static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { |
| 53 | 89 | T pojo = PODAM_FACTORY.manufacturePojo(clazz); |
| 54 | 90 | // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 | ... | ... |
src/test/resources/application-unit-test.yaml
| ... | ... | @@ -10,6 +10,8 @@ spring: |
| 10 | 10 | - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration # 单元测试,禁用 SpringSecurity |
| 11 | 11 | - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 单元测试,禁用 Quartz |
| 12 | 12 | - com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration # 单元测试,禁用 Lock4j 分布式锁 |
| 13 | + - org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration # 单元测试,禁用 Scheduler 定时任务 | |
| 14 | + - org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration # 项目没有使用 Spring Data,所以禁用配置类,加速启动 | |
| 13 | 15 | |
| 14 | 16 | # Swagger 接口文档的自动配置(单元测试,禁用 Swagger) |
| 15 | 17 | springfox: | ... | ... |