增加 podam 随机生成对象,简化单元测试的成本

This commit is contained in:
YunaiV 2021-03-03 01:33:05 +08:00
parent 92997a0cd5
commit 632be011b3
7 changed files with 55 additions and 35 deletions

View File

@ -190,6 +190,13 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>uk.co.jemos.podam</groupId> <!-- 单元测试,随机生成 POJO 类 -->
<artifactId>podam</artifactId>
<version>7.2.6.RELEASE</version>
<scope>test</scope>
</dependency>
<!-- 工具类相关 --> <!-- 工具类相关 -->
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>

View File

@ -122,7 +122,7 @@ public class DBConfigRepository extends AbstractConfigRepository {
private Properties buildProperties(List<InfConfigDO> configs) { private Properties buildProperties(List<InfConfigDO> configs) {
Properties properties = propertiesFactory.getPropertiesInstance(); Properties properties = propertiesFactory.getPropertiesInstance();
configs.stream().filter(config -> 0 == config.getDeleted()) // 过滤掉被删除的配置 configs.stream().filter(BaseDO::getDeleted) // 过滤掉被删除的配置
.forEach(config -> properties.put(config.getKey(), config.getValue())); .forEach(config -> properties.put(config.getKey(), config.getValue()));
return properties; return properties;
} }

View File

@ -32,6 +32,6 @@ public class BaseDO implements Serializable {
* 是否删除 * 是否删除
*/ */
@TableLogic @TableLogic
private Integer deleted; private Boolean deleted;
} }

View File

@ -85,7 +85,7 @@ public class SysAuthServiceImpl implements SysAuthService {
@Override @Override
public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) { public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) {
// 判断验证码是否正确 // 判断验证码是否正确
// this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode()); this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
// 使用账号密码进行登陆 // 使用账号密码进行登陆
LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
@ -99,11 +99,13 @@ public class SysAuthServiceImpl implements SysAuthService {
String code = captchaService.getCaptchaCode(captchaUUID); String code = captchaService.getCaptchaCode(captchaUUID);
// 验证码不存在 // 验证码不存在
if (code == null) { if (code == null) {
// 创建登陆失败日志验证码不存在
this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND); this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND); throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_NOT_FOUND);
} }
// 验证码不正确 // 验证码不正确
if (!code.equals(captchaCode)) { if (!code.equals(captchaCode)) {
// 创建登陆失败日志验证码不正确)
this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR); this.createLoginLog(username, SysLoginResultEnum.CAPTCHA_CODE_ERROR);
throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR); throw ServiceExceptionUtil.exception(AUTH_LOGIN_CAPTCHA_CODE_ERROR);
} }

View File

@ -1,15 +1,19 @@
package cn.iocoder.dashboard.modules.system.service.auth; package cn.iocoder.dashboard.modules.system.service.auth;
import cn.iocoder.dashboard.BaseSpringBootUnitTest; import cn.iocoder.dashboard.BaseSpringBootUnitTest;
import cn.iocoder.dashboard.framework.security.core.LoginUser;
import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; 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.auth.impl.SysAuthServiceImpl;
import cn.iocoder.dashboard.modules.system.service.user.SysUserService; import cn.iocoder.dashboard.modules.system.service.user.SysUserService;
import cn.iocoder.dashboard.util.AssertUtils;
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 static cn.iocoder.dashboard.util.RandomUtils.*; 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 org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@ -28,6 +32,12 @@ public class SysAuthServiceImplTest extends BaseSpringBootUnitTest {
// mock 方法 // mock 方法
SysUserDO user = randomUserDO(); SysUserDO user = randomUserDO();
when(userService.getUserByUserName(eq(username))).thenReturn(user); when(userService.getUserByUserName(eq(username))).thenReturn(user);
// 调用
LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username);
// 校验
AssertUtils.assertEquals(user, loginUser, "updateTime");
assertNull(loginUser.getRoleIds()); // 此时不会加载角色所以是空的
} }
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.dashboard.util; package cn.iocoder.dashboard.util;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.dashboard.common.exception.ErrorCode; import cn.iocoder.dashboard.common.exception.ErrorCode;
import cn.iocoder.dashboard.common.exception.ServiceException; import cn.iocoder.dashboard.common.exception.ServiceException;
@ -22,10 +23,15 @@ public class AssertUtils {
* *
* @param expected 期望对象 * @param expected 期望对象
* @param actual 实际对象 * @param actual 实际对象
* @param ignoreFields 忽略的属性数组
*/ */
public static void assertEquals(Object expected, Object actual) { public static void assertEquals(Object expected, Object actual, String... ignoreFields) {
Field[] expectedFields = ReflectUtil.getFields(expected.getClass()); Field[] expectedFields = ReflectUtil.getFields(expected.getClass());
Arrays.stream(expectedFields).forEach(expectedField -> { Arrays.stream(expectedFields).forEach(expectedField -> {
// 如果是忽略的属性则不进行比对
if (ArrayUtil.contains(ignoreFields, expectedField.getName())) {
return;
}
// 忽略不存在的属性 // 忽略不存在的属性
Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName()); Field actualField = ReflectUtil.getField(actual.getClass(), expectedField.getName());
if (actualField == null) { if (actualField == null) {

View File

@ -1,9 +1,14 @@
package cn.iocoder.dashboard.util; package cn.iocoder.dashboard.util;
import cn.hutool.core.util.*; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.iocoder.dashboard.modules.system.dal.dataobject.user.SysUserDO; 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.lang.reflect.Field; import java.util.Arrays;
import java.util.Date;
import java.util.function.Consumer;
/** /**
* 随机工具类 * 随机工具类
@ -14,6 +19,10 @@ public class RandomUtils {
private static final int RANDOM_STRING_LENGTH = 10; private static final int RANDOM_STRING_LENGTH = 10;
private static final int RANDOM_DATE_MAX = 30;
private static final PodamFactory PODAM_FACTORY = new PodamFactoryImpl();
public static String randomString() { public static String randomString() {
return RandomUtil.randomString(RANDOM_STRING_LENGTH); return RandomUtil.randomString(RANDOM_STRING_LENGTH);
} }
@ -26,41 +35,27 @@ public class RandomUtils {
return RandomUtil.randomInt(0, Integer.MAX_VALUE); return RandomUtil.randomInt(0, Integer.MAX_VALUE);
} }
public static Date randomDate() {
return RandomUtil.randomDay(0, RANDOM_DATE_MAX);
}
public static Short randomShort() { public static Short randomShort() {
return (short) RandomUtil.randomInt(0, Short.MAX_VALUE); return (short) RandomUtil.randomInt(0, Short.MAX_VALUE);
} }
public static SysUserDO randomUserDO() { @SafeVarargs
SysUserDO user = randomObject(SysUserDO.class); public static SysUserDO randomUserDO(Consumer<SysUserDO>... consumers) {
return user; return randomPojo(SysUserDO.class, consumers);
} }
private static <T> T randomObject(Class<T> clazz) { @SafeVarargs
// 创建对象 private static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
T object = ReflectUtil.newInstance(clazz); T pojo = PODAM_FACTORY.manufacturePojo(clazz);
// 遍历属性设置随机值 // 非空时回调逻辑通过它可以实现 Pojo 的进一步处理
for (Field field : ReflectUtil.getFields(clazz)) { if (ArrayUtil.isNotEmpty(consumers)) {
// 数字类型 Arrays.stream(consumers).forEach(consumer -> consumer.accept(pojo));
if (field.getType() == Long.class) {
ReflectUtil.setFieldValue(object, field, randomLong());
continue;
} }
if (field.getType() == Integer.class) { return pojo;
ReflectUtil.setFieldValue(object, field, randomInteger());
continue;
}
if (field.getType() == Short.class) {
ReflectUtil.setFieldValue(object, field, randomShort());
continue;
}
// 字符串类型
if (field.getType() == String.class) {
ReflectUtil.setFieldValue(object, field, randomString());
continue;
}
// System.out.println();
}
return object;
} }
} }