mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
会员:完善会员等级校验、单元测试
This commit is contained in:
parent
e2032e7e97
commit
f884054d2c
@ -29,8 +29,8 @@ create table member_level_log
|
||||
level_id bigint default 0 not null comment '等级编号',
|
||||
level int default 0 not null comment '会员等级',
|
||||
discount int(4) default 100 not null comment '享受折扣',
|
||||
experience int(4) default 100 not null comment '升级经验',
|
||||
user_experience int(4) default 100 not null comment '会员此时的经验',
|
||||
experience int(4) default 0 not null comment '升级经验',
|
||||
user_experience int(4) default 0 not null comment '会员此时的经验',
|
||||
remark varchar(255) default '' not null comment '备注',
|
||||
description varchar(255) default '' not null comment '描述',
|
||||
creator varchar(64) default '' null comment '创建者',
|
||||
|
@ -44,6 +44,11 @@ public interface ErrorCodeConstants {
|
||||
|
||||
//========== 会员等级 1004007000 ==========
|
||||
ErrorCode LEVEL_NOT_EXISTS = new ErrorCode(1004007000, "会员等级不存在");
|
||||
ErrorCode LEVEL_NAME_EXISTS = new ErrorCode(1004007001, "会员等级名称[{}]已被使用");
|
||||
ErrorCode LEVEL_VALUE_EXISTS = new ErrorCode(1004007002, "会员等级值[{}]已被[{}]使用");
|
||||
ErrorCode LEVEL_EXPERIENCE_MIN = new ErrorCode(1004007003, "升级经验必须大于上一个等级[{}]设置的升级经验[{}]");
|
||||
ErrorCode LEVEL_EXPERIENCE_MAX = new ErrorCode(1004007004, "升级经验必须小于下一个等级[{}]设置的升级经验[{}]");
|
||||
|
||||
ErrorCode LEVEL_LOG_NOT_EXISTS = new ErrorCode(1004007100, "会员等级记录不存在");
|
||||
ErrorCode EXPERIENCE_LOG_NOT_EXISTS = new ErrorCode(1004007200, "会员经验记录不存在");
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ public class MemberLevelBaseVO {
|
||||
|
||||
@Schema(description = "等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "等级不能为空")
|
||||
@Positive(message = "等级必须大于0")
|
||||
private Integer level;
|
||||
|
||||
@Schema(description = "享受折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "98")
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.member.service.level;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelCreateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelPageReqVO;
|
||||
@ -7,6 +9,7 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelUpdat
|
||||
import cn.iocoder.yudao.module.member.convert.level.MemberLevelConvert;
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -16,7 +19,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.LEVEL_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 会员等级 Service 实现类
|
||||
@ -33,6 +36,9 @@ public class MemberLevelServiceImpl implements MemberLevelService {
|
||||
|
||||
@Override
|
||||
public Long createLevel(MemberLevelCreateReqVO createReqVO) {
|
||||
// 校验配置是否有效
|
||||
validateConfigValid(null, createReqVO.getName(), createReqVO.getLevel(), createReqVO.getExperience());
|
||||
|
||||
// 插入
|
||||
MemberLevelDO level = MemberLevelConvert.INSTANCE.convert(createReqVO);
|
||||
levelMapper.insert(level);
|
||||
@ -44,6 +50,9 @@ public class MemberLevelServiceImpl implements MemberLevelService {
|
||||
public void updateLevel(MemberLevelUpdateReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validateLevelExists(updateReqVO.getId());
|
||||
// 校验配置是否有效
|
||||
validateConfigValid(updateReqVO.getId(), updateReqVO.getName(), updateReqVO.getLevel(), updateReqVO.getExperience());
|
||||
|
||||
// 更新
|
||||
MemberLevelDO updateObj = MemberLevelConvert.INSTANCE.convert(updateReqVO);
|
||||
levelMapper.updateById(updateObj);
|
||||
@ -57,10 +66,72 @@ public class MemberLevelServiceImpl implements MemberLevelService {
|
||||
levelMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validateLevelExists(Long id) {
|
||||
if (levelMapper.selectById(id) == null) {
|
||||
@VisibleForTesting
|
||||
MemberLevelDO validateLevelExists(Long id) {
|
||||
MemberLevelDO levelDO = levelMapper.selectById(id);
|
||||
if (levelDO == null) {
|
||||
throw exception(LEVEL_NOT_EXISTS);
|
||||
}
|
||||
return levelDO;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateNameUnique(List<MemberLevelDO> list, Long id, String name) {
|
||||
for (MemberLevelDO levelDO : list) {
|
||||
if (ObjUtil.notEqual(levelDO.getName(), name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id == null || !id.equals(levelDO.getId())) {
|
||||
throw exception(LEVEL_NAME_EXISTS, levelDO.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateLevelUnique(List<MemberLevelDO> list, Long id, Integer level) {
|
||||
for (MemberLevelDO levelDO : list) {
|
||||
if (ObjUtil.notEqual(levelDO.getLevel(), level)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id == null || !id.equals(levelDO.getId())) {
|
||||
throw exception(LEVEL_VALUE_EXISTS, levelDO.getLevel(), levelDO.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateExperienceOutRange(List<MemberLevelDO> list, Long id, Integer level, Integer experience) {
|
||||
for (MemberLevelDO levelDO : list) {
|
||||
if (levelDO.getId().equals(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (levelDO.getLevel() < level) {
|
||||
// 经验大于前一个等级
|
||||
if (experience <= levelDO.getExperience()) {
|
||||
throw exception(LEVEL_EXPERIENCE_MIN, levelDO.getName(), levelDO.getExperience());
|
||||
}
|
||||
} else if (levelDO.getLevel() > level) {
|
||||
//小于下一个级别
|
||||
if (experience >= levelDO.getExperience()) {
|
||||
throw exception(LEVEL_EXPERIENCE_MAX, levelDO.getName(), levelDO.getExperience());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void validateConfigValid(Long id, String name, Integer level, Integer experience) {
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
|
||||
// 校验名称唯一
|
||||
validateNameUnique(list, id, name);
|
||||
// 校验等级唯一
|
||||
validateLevelUnique(list, id, level);
|
||||
// 校验升级所需经验是否有效: 大于前一个等级,小于下一个级别
|
||||
validateExperienceOutRange(list, id, level, experience);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.member.service.level;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelCreateReqVO;
|
||||
import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelPageReqVO;
|
||||
@ -8,16 +10,19 @@ import cn.iocoder.yudao.module.member.controller.admin.level.vo.MemberLevelUpdat
|
||||
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberLevelDO;
|
||||
import cn.iocoder.yudao.module.member.dal.mysql.level.MemberLevelMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.randomInt;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.LEVEL_NOT_EXISTS;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
@ -34,10 +39,19 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
|
||||
@Resource
|
||||
private MemberLevelMapper levelMapper;
|
||||
|
||||
@MockBean
|
||||
private MemberLevelLogService memberLevelLogService;
|
||||
@MockBean
|
||||
private MemberExperienceLogService memberExperienceLogService;
|
||||
|
||||
@Test
|
||||
public void testCreateLevel_success() {
|
||||
// 准备参数
|
||||
MemberLevelCreateReqVO reqVO = randomPojo(MemberLevelCreateReqVO.class);
|
||||
MemberLevelCreateReqVO reqVO = randomPojo(MemberLevelCreateReqVO.class, o -> {
|
||||
o.setDiscount(randomInt());
|
||||
o.setIcon(randomURL());
|
||||
o.setBackgroundUrl(randomURL());
|
||||
});
|
||||
|
||||
// 调用
|
||||
Long levelId = levelService.createLevel(reqVO);
|
||||
@ -56,6 +70,14 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
|
||||
// 准备参数
|
||||
MemberLevelUpdateReqVO reqVO = randomPojo(MemberLevelUpdateReqVO.class, o -> {
|
||||
o.setId(dbLevel.getId()); // 设置更新的 ID
|
||||
//以下要保持一致
|
||||
o.setName(dbLevel.getName());
|
||||
o.setLevel(dbLevel.getLevel());
|
||||
o.setExperience(dbLevel.getExperience());
|
||||
//以下是要修改的字段
|
||||
o.setDiscount(randomInt());
|
||||
o.setIcon(randomURL());
|
||||
o.setBackgroundUrl(randomURL());
|
||||
});
|
||||
|
||||
// 调用
|
||||
@ -106,9 +128,9 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
|
||||
});
|
||||
levelMapper.insert(dbLevel);
|
||||
// 测试 name 不匹配
|
||||
levelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setName(null)));
|
||||
levelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setName("")));
|
||||
// 测试 status 不匹配
|
||||
levelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setStatus(null)));
|
||||
levelMapper.insert(cloneIgnoreId(dbLevel, o -> o.setStatus(0)));
|
||||
// 准备参数
|
||||
MemberLevelPageReqVO reqVO = new MemberLevelPageReqVO();
|
||||
reqVO.setName("黄金会员");
|
||||
@ -122,4 +144,121 @@ public class MemberLevelServiceImplTest extends BaseDbUnitTest {
|
||||
assertPojoEquals(dbLevel, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLevel_nameUnique() {
|
||||
// 准备参数
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> o.setName(name)));
|
||||
|
||||
// 调用,校验异常
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
assertServiceException(() -> levelService.validateNameUnique(list, null, name), LEVEL_NAME_EXISTS, name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLevel_nameUnique() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> o.setName(name)));
|
||||
|
||||
// 调用,校验异常
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
assertServiceException(() -> levelService.validateNameUnique(list, id, name), LEVEL_NAME_EXISTS, name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLevel_levelUnique() {
|
||||
// 准备参数
|
||||
Integer level = randomInteger();
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> {
|
||||
o.setLevel(level);
|
||||
o.setName(name);
|
||||
}));
|
||||
|
||||
// 调用,校验异常
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
assertServiceException(() -> levelService.validateLevelUnique(list, null, level), LEVEL_VALUE_EXISTS, level, name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLevel_levelUnique() {
|
||||
// 准备参数
|
||||
Long id = randomLongId();
|
||||
Integer level = randomInteger();
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> {
|
||||
o.setLevel(level);
|
||||
o.setName(name);
|
||||
}));
|
||||
|
||||
// 调用,校验异常
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
assertServiceException(() -> levelService.validateLevelUnique(list, id, level), LEVEL_VALUE_EXISTS, level, name);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateLevel_experienceOutRange() {
|
||||
// 准备参数
|
||||
int level = 10;
|
||||
int experience = 10;
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> {
|
||||
o.setLevel(level);
|
||||
o.setExperience(experience);
|
||||
o.setName(name);
|
||||
}));
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> levelService.validateExperienceOutRange(list, null, level + 1, experience - 1), LEVEL_EXPERIENCE_MIN, name, level);
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> levelService.validateExperienceOutRange(list, null, level - 1, experience + 1), LEVEL_EXPERIENCE_MAX, name, level);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateLevel_experienceOutRange() {
|
||||
// 准备参数
|
||||
int level = 10;
|
||||
int experience = 10;
|
||||
Long id = randomLongId();
|
||||
String name = randomString();
|
||||
|
||||
// mock 数据
|
||||
levelMapper.insert(randomLevelDO(o -> {
|
||||
o.setLevel(level);
|
||||
o.setExperience(experience);
|
||||
o.setName(name);
|
||||
}));
|
||||
List<MemberLevelDO> list = levelMapper.selectList();
|
||||
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> levelService.validateExperienceOutRange(list, id, level + 1, experience - 1), LEVEL_EXPERIENCE_MIN, name, level);
|
||||
// 调用,校验异常
|
||||
assertServiceException(() -> levelService.validateExperienceOutRange(list, id, level - 1, experience + 1), LEVEL_EXPERIENCE_MAX, name, level);
|
||||
}
|
||||
|
||||
// ========== 随机对象 ==========
|
||||
|
||||
@SafeVarargs
|
||||
private static MemberLevelDO randomLevelDO(Consumer<MemberLevelDO>... consumers) {
|
||||
Consumer<MemberLevelDO> consumer = (o) -> {
|
||||
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
o.setDiscount(randomInt(0, 100));
|
||||
o.setIcon(randomURL());
|
||||
o.setBackgroundUrl(randomURL());
|
||||
};
|
||||
return randomPojo(MemberLevelDO.class, ArrayUtils.append(consumer, consumers));
|
||||
}
|
||||
}
|
||||
|
@ -51,10 +51,10 @@ CREATE TABLE IF NOT EXISTS "member_level"
|
||||
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
|
||||
"name" varchar NOT NULL,
|
||||
"experience" int NOT NULL,
|
||||
"value" int NOT NULL,
|
||||
"level" int NOT NULL,
|
||||
"discount" int NOT NULL,
|
||||
"icon" varchar NOT NULL,
|
||||
"bg_url" varchar NOT NULL,
|
||||
"background_url" varchar NOT NULL,
|
||||
"creator" varchar DEFAULT '',
|
||||
"create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updater" varchar DEFAULT '',
|
||||
|
Loading…
Reference in New Issue
Block a user