Commit fcad34a5bf602e0179d8e28aa5b09c23a64c39e4

Authored by YunaiV
1 parent 632be011

inf_config Service 的单元测试

src/main/java/cn/iocoder/dashboard/modules/infra/controller/config/vo/InfConfigBaseVO.java
@@ -17,7 +17,7 @@ public class InfConfigBaseVO { @@ -17,7 +17,7 @@ public class InfConfigBaseVO {
17 17
18 @ApiModelProperty(value = "参数分组", required = true, example = "biz") 18 @ApiModelProperty(value = "参数分组", required = true, example = "biz")
19 @NotEmpty(message = "参数分组不能为空") 19 @NotEmpty(message = "参数分组不能为空")
20 - @Size(max = 100, message = "参数名称不能超过50个字符") 20 + @Size(max = 50, message = "参数名称不能超过50个字符")
21 private String group; 21 private String group;
22 22
23 @ApiModelProperty(value = "参数名称", required = true, example = "数据库名") 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,11 +30,11 @@ import org.springframework.stereotype.Service;
30 import org.springframework.util.Assert; 30 import org.springframework.util.Assert;
31 31
32 import javax.annotation.Resource; 32 import javax.annotation.Resource;
33 -import java.util.Collections;  
34 import java.util.Set; 33 import java.util.Set;
35 34
36 import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception; 35 import static cn.iocoder.dashboard.common.exception.util.ServiceExceptionUtil.exception;
37 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*; 36 import static cn.iocoder.dashboard.modules.system.enums.SysErrorCodeConstants.*;
  37 +import static java.util.Collections.singleton;
38 38
39 /** 39 /**
40 * Auth Service 实现类 40 * Auth Service 实现类
@@ -155,7 +155,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -155,7 +155,7 @@ public class SysAuthServiceImpl implements SysAuthService {
155 * @return 角色编号数组 155 * @return 角色编号数组
156 */ 156 */
157 private Set<Long> getUserRoleIds(Long userId) { 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 @Override 161 @Override
src/main/java/cn/iocoder/dashboard/modules/system/service/permission/SysPermissionService.java
@@ -42,7 +42,7 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService @@ -42,7 +42,7 @@ public interface SysPermissionService extends SecurityPermissionFrameworkService
42 * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤 42 * @param roleStatuses 角色状态集合. 允许为空,为空时不过滤
43 * @return 角色编号集合 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,7 +151,7 @@ public class SysPermissionServiceImpl implements SysPermissionService {
151 } 151 }
152 152
153 @Override 153 @Override
154 - public Set<Long> listUserRoleIds(Long userId, Collection<Integer> roleStatuses) { 154 + public Set<Long> getUserRoleIds(Long userId, Collection<Integer> roleStatuses) {
155 List<SysUserRoleDO> userRoleList = userRoleMapper.selectListByUserId(userId); 155 List<SysUserRoleDO> userRoleList = userRoleMapper.selectListByUserId(userId);
156 // 过滤角色状态 156 // 过滤角色状态
157 if (CollectionUtil.isNotEmpty(roleStatuses)) { 157 if (CollectionUtil.isNotEmpty(roleStatuses)) {
src/main/resources/application.yaml
@@ -24,7 +24,7 @@ spring: @@ -24,7 +24,7 @@ spring:
24 mybatis-plus: 24 mybatis-plus:
25 configuration: 25 configuration:
26 map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 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 global-config: 28 global-config:
29 db-config: 29 db-config:
30 id-type: AUTO # 自增 ID 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 +11,13 @@ import cn.iocoder.dashboard.modules.infra.service.config.impl.InfConfigServiceIm
11 import cn.iocoder.dashboard.util.AssertUtils; 11 import cn.iocoder.dashboard.util.AssertUtils;
12 import org.junit.jupiter.api.Test; 12 import org.junit.jupiter.api.Test;
13 import org.springframework.boot.test.mock.mockito.MockBean; 13 import org.springframework.boot.test.mock.mockito.MockBean;
14 -import org.springframework.test.context.jdbc.Sql;  
15 14
16 import javax.annotation.Resource; 15 import javax.annotation.Resource;
17 16
  17 +import static cn.hutool.core.util.RandomUtil.randomEle;
18 import static cn.iocoder.dashboard.modules.infra.enums.InfErrorCodeConstants.CONFIG_KEY_DUPLICATE; 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 import static org.junit.jupiter.api.Assertions.*; 21 import static org.junit.jupiter.api.Assertions.*;
20 import static org.mockito.Mockito.times; 22 import static org.mockito.Mockito.times;
21 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.verify;
@@ -34,13 +36,7 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { @@ -34,13 +36,7 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest {
34 @Test 36 @Test
35 public void testCreateConfig_success() { 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 // mock 40 // mock
45 41
46 // 调用 42 // 调用
@@ -56,17 +52,14 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest { @@ -56,17 +52,14 @@ public class InfConfigServiceImplTest extends BaseSpringBootUnitTest {
56 } 52 }
57 53
58 @Test 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 public void testCreateConfig_keyDuplicate() { 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 ServiceException serviceException = assertThrows(ServiceException.class, () -> configService.createConfig(reqVO)); 65 ServiceException serviceException = assertThrows(ServiceException.class, () -> configService.createConfig(reqVO));
src/test/java/cn/iocoder/dashboard/modules/system/service/auth/SysAuthServiceImplTest.java
1 package cn.iocoder.dashboard.modules.system.service.auth; 1 package cn.iocoder.dashboard.modules.system.service.auth;
2 2
3 import cn.iocoder.dashboard.BaseSpringBootUnitTest; 3 import cn.iocoder.dashboard.BaseSpringBootUnitTest;
  4 +import cn.iocoder.dashboard.common.enums.CommonStatusEnum;
4 import cn.iocoder.dashboard.framework.security.core.LoginUser; 5 import cn.iocoder.dashboard.framework.security.core.LoginUser;
5 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; 6 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
6 import cn.iocoder.dashboard.modules.system.service.auth.impl.SysAuthServiceImpl; 7 import cn.iocoder.dashboard.modules.system.service.auth.impl.SysAuthServiceImpl;
  8 +import cn.iocoder.dashboard.modules.system.service.permission.SysPermissionService;
7 import cn.iocoder.dashboard.modules.system.service.user.SysUserService; 9 import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
8 import cn.iocoder.dashboard.util.AssertUtils; 10 import cn.iocoder.dashboard.util.AssertUtils;
9 import org.junit.jupiter.api.Test; 11 import org.junit.jupiter.api.Test;
10 import org.springframework.boot.test.mock.mockito.MockBean; 12 import org.springframework.boot.test.mock.mockito.MockBean;
  13 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
11 14
12 import javax.annotation.Resource; 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 import static org.mockito.ArgumentMatchers.eq; 21 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.when; 22 import static org.mockito.Mockito.when;
19 23
@@ -24,13 +28,15 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { @@ -24,13 +28,15 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest {
24 28
25 @MockBean 29 @MockBean
26 private SysUserService userService; 30 private SysUserService userService;
  31 + @MockBean
  32 + private SysPermissionService permissionService;
27 33
28 @Test 34 @Test
29 public void testLoadUserByUsername_success() { 35 public void testLoadUserByUsername_success() {
30 // 准备参数 36 // 准备参数
31 String username = randomString(); 37 String username = randomString();
32 // mock 方法 38 // mock 方法
33 - SysUserDO user = randomUserDO(); 39 + SysUserDO user = randomUserDO(o -> o.setUsername(username));
34 when(userService.getUserByUserName(eq(username))).thenReturn(user); 40 when(userService.getUserByUserName(eq(username))).thenReturn(user);
35 41
36 // 调用 42 // 调用
@@ -40,4 +46,47 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest { @@ -40,4 +46,47 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest {
40 assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的 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,13 +2,18 @@ package cn.iocoder.dashboard.util;
2 2
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
4 import cn.hutool.core.util.RandomUtil; 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 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; 7 import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO;
6 import uk.co.jemos.podam.api.PodamFactory; 8 import uk.co.jemos.podam.api.PodamFactory;
7 import uk.co.jemos.podam.api.PodamFactoryImpl; 9 import uk.co.jemos.podam.api.PodamFactoryImpl;
8 10
9 import java.util.Arrays; 11 import java.util.Arrays;
10 import java.util.Date; 12 import java.util.Date;
  13 +import java.util.Set;
11 import java.util.function.Consumer; 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,8 +26,24 @@ public class RandomUtils {
21 26
22 private static final int RANDOM_DATE_MAX = 30; 27 private static final int RANDOM_DATE_MAX = 30;
23 28
  29 + private static final int RANDOM_COLLECTION_LENGTH = 5;
  30 +
24 private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl(); 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 public static String randomString() { 47 public static String randomString() {
27 return RandomUtil.randomString(RANDOM_STRING_LENGTH); 48 return RandomUtil.randomString(RANDOM_STRING_LENGTH);
28 } 49 }
@@ -43,12 +64,27 @@ public class RandomUtils { @@ -43,12 +64,27 @@ public class RandomUtils {
43 return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); 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 @SafeVarargs 72 @SafeVarargs
47 public static SysUserDO randomUserDO(Consumer<SysUserDO>... consumers) { 73 public static SysUserDO randomUserDO(Consumer<SysUserDO>... consumers) {
48 return randomPojo(SysUserDO.class, consumers); 74 return randomPojo(SysUserDO.class, consumers);
49 } 75 }
50 76
51 @SafeVarargs 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 private static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) { 88 private static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
53 T pojo = PODAM_FACTORY.manufacturePojo(clazz); 89 T pojo = PODAM_FACTORY.manufacturePojo(clazz);
54 // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理 90 // 非空时,回调逻辑。通过它,可以实现 Pojo 的进一步处理
src/test/resources/application-unit-test.yaml
@@ -10,6 +10,8 @@ spring: @@ -10,6 +10,8 @@ spring:
10 - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration # 单元测试,禁用 SpringSecurity 10 - org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration # 单元测试,禁用 SpringSecurity
11 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 单元测试,禁用 Quartz 11 - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 单元测试,禁用 Quartz
12 - com.baomidou.lock.spring.boot.autoconfigure.LockAutoConfiguration # 单元测试,禁用 Lock4j 分布式锁 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 # Swagger 接口文档的自动配置(单元测试,禁用 Swagger) 16 # Swagger 接口文档的自动配置(单元测试,禁用 Swagger)
15 springfox: 17 springfox: