修改了代码结构
This commit is contained in:
@ -91,27 +91,7 @@ public class ProjectController {
|
||||
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
|
||||
// @SysLog(title = "项目管理", content = "小程序用户查看项目列表")
|
||||
public BaseResponse<List<ProjectCardVO>> queryProjectCardList(HttpServletRequest request) {
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
// 获取项目明细抽佣列表
|
||||
List<ProjectCommission> projectCommissionList = commonService.findByFieldEqTargetField(ProjectCommission::getUserId, userId, projectCommissionService);
|
||||
// 封装Map集合(键:项目id, 值:项目总价)
|
||||
Map<Long, BigDecimal> projectPriceMap = new HashMap<>();
|
||||
for (ProjectCommission projectCommission : projectCommissionList) {
|
||||
Long projectId = projectCommission.getProjectId();
|
||||
BigDecimal projectPrice = projectPriceMap.get(projectId);
|
||||
if (projectPrice == null) {
|
||||
projectPrice = projectCommission.getMyUnitPrice();
|
||||
} else {
|
||||
projectPrice = projectPrice.add(projectCommission.getMyUnitPrice());
|
||||
}
|
||||
projectPriceMap.put(projectId, projectPrice);
|
||||
}
|
||||
List<Project> projectList = commonService.findByFieldEqTargetField(Project::getIsShelves, 1, projectService);
|
||||
for (Project project : projectList) {
|
||||
BigDecimal projectPrice = projectPriceMap.get(project.getId());
|
||||
project.setProjectPrice(projectPrice == null ? BigDecimal.ZERO : projectPrice);
|
||||
}
|
||||
List<ProjectCardVO> projectCardVOS = commonService.convertList(projectList, ProjectCardVO.class);
|
||||
List<ProjectCardVO> projectCardVOS = projectService.queryProjectCardList(request);
|
||||
return ResultUtils.success(projectCardVOS);
|
||||
}
|
||||
|
||||
@ -281,10 +261,7 @@ public class ProjectController {
|
||||
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
|
||||
@SysLog(title = "项目管理", content = "web端管理员根据id查询项目")
|
||||
public BaseResponse<ProjectVO> queryProjectById(@Valid @RequestBody CommonRequest commonRequest) {
|
||||
Long id = commonRequest.getId();
|
||||
Project project = projectService.getById(id);
|
||||
ThrowUtils.throwIf(project == null, ErrorCode.OPERATION_ERROR, "当前项目不存在");
|
||||
ProjectVO projectVO = commonService.copyProperties(project, ProjectVO.class);
|
||||
ProjectVO projectVO = projectService.queryProjectById(commonRequest);
|
||||
return ResultUtils.success(projectVO);
|
||||
}
|
||||
|
||||
|
@ -114,12 +114,7 @@ public class PromoCodeController {
|
||||
@RequiresPermission(mustRole = UserConstant.ADMIN_ROLE)
|
||||
@SysLog(title = "推广码管理", content = "web端管理员批量删除推广码")
|
||||
public BaseResponse<Boolean> delBatchPromoCode(@Valid @RequestBody CommonBatchRequest commonBatchRequest) {
|
||||
List<Long> ids = commonBatchRequest.getIds();
|
||||
LambdaQueryWrapper<PromoCode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.in(PromoCode::getId, ids).eq(PromoCode::getPromoCodeStatus, true);
|
||||
List<PromoCode> promoCodeList = promoCodeService.list(lambdaQueryWrapper);
|
||||
ThrowUtils.throwIf(promoCodeList.size() > 0, ErrorCode.OPERATION_ERROR, "当前推广码正在使用中,无法删除");
|
||||
promoCodeService.removeByIds(ids);
|
||||
promoCodeService.delBatchPromoCode(commonBatchRequest);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
|
@ -58,10 +58,7 @@ public class UserAccountController {
|
||||
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
|
||||
// @SysLog(title = "用户账户管理", content = "小程序端用户添加用户账户")
|
||||
public BaseResponse<Boolean> addUserAccount(@Valid @RequestBody UserAccountAddRequest userAccountAddRequest, HttpServletRequest request) {
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
UserAccount userAccount = commonService.copyProperties(userAccountAddRequest, UserAccount.class);
|
||||
userAccount.setUserId(userId);
|
||||
userAccountService.save(userAccount);
|
||||
userAccountService.addUserAccount(userAccountAddRequest, request);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
@ -75,10 +72,7 @@ public class UserAccountController {
|
||||
@RequiresPermission(mustRole = UserConstant.DEFAULT_ROLE)
|
||||
// @SysLog(title = "用户账户管理", content = "小程序端用户根据id修改用户账户信息")
|
||||
public BaseResponse<Boolean> updateUserAccount(@Valid @RequestBody UserAccountUpdateRequest userAccountUpdateRequest, HttpServletRequest request) {
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
UserAccount userAccount = commonService.copyProperties(userAccountUpdateRequest, UserAccount.class);
|
||||
userAccount.setUserId(userId);
|
||||
userAccountService.updateById(userAccount);
|
||||
userAccountService.updateUserAccount(userAccountUpdateRequest, request);
|
||||
return ResultUtils.success(true);
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,17 @@
|
||||
package com.greenorange.promotion.model.vo.project;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProjectCardVO implements Serializable {
|
||||
|
||||
/**
|
||||
|
@ -1,9 +1,15 @@
|
||||
package com.greenorange.promotion.service.project;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.greenorange.promotion.model.dto.CommonRequest;
|
||||
import com.greenorange.promotion.model.dto.project.ProjectQueryRequest;
|
||||
import com.greenorange.promotion.model.entity.Project;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.greenorange.promotion.model.vo.project.ProjectCardVO;
|
||||
import com.greenorange.promotion.model.vo.project.ProjectVO;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 35880
|
||||
@ -17,4 +23,17 @@ public interface ProjectService extends IService<Project> {
|
||||
* 获取查询条件
|
||||
*/
|
||||
QueryWrapper<Project> getQueryWrapper(ProjectQueryRequest projectQueryRequest);
|
||||
|
||||
|
||||
/**
|
||||
* 小程序用户查看项目列表
|
||||
* @return 项目列表
|
||||
*/
|
||||
List<ProjectCardVO> queryProjectCardList(HttpServletRequest request);
|
||||
|
||||
|
||||
/**
|
||||
* web端管理员根据id查询项目
|
||||
*/
|
||||
ProjectVO queryProjectById(CommonRequest commonRequest);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.greenorange.promotion.service.project;
|
||||
|
||||
import com.greenorange.promotion.model.dto.CommonBatchRequest;
|
||||
import com.greenorange.promotion.model.entity.PromoCode;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
@ -10,4 +11,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface PromoCodeService extends IService<PromoCode> {
|
||||
|
||||
|
||||
/**
|
||||
* web端管理员批量删除推广码
|
||||
*/
|
||||
void delBatchPromoCode(CommonBatchRequest commonBatchRequest);
|
||||
}
|
||||
|
@ -2,16 +2,32 @@ package com.greenorange.promotion.service.project.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.greenorange.promotion.common.ErrorCode;
|
||||
import com.greenorange.promotion.common.ResultUtils;
|
||||
import com.greenorange.promotion.constant.CommonConstant;
|
||||
import com.greenorange.promotion.exception.ThrowUtils;
|
||||
import com.greenorange.promotion.model.dto.CommonRequest;
|
||||
import com.greenorange.promotion.model.dto.project.ProjectQueryRequest;
|
||||
import com.greenorange.promotion.model.entity.Project;
|
||||
import com.greenorange.promotion.model.entity.ProjectCommission;
|
||||
import com.greenorange.promotion.model.entity.UserInfo;
|
||||
import com.greenorange.promotion.model.vo.project.ProjectCardVO;
|
||||
import com.greenorange.promotion.model.vo.project.ProjectVO;
|
||||
import com.greenorange.promotion.service.common.CommonService;
|
||||
import com.greenorange.promotion.service.project.ProjectCommissionService;
|
||||
import com.greenorange.promotion.service.project.ProjectService;
|
||||
import com.greenorange.promotion.mapper.ProjectMapper;
|
||||
import com.greenorange.promotion.utils.SqlUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 35880
|
||||
* @description 针对表【project(项目表)】的数据库操作Service实现
|
||||
@ -21,6 +37,19 @@ import org.springframework.stereotype.Service;
|
||||
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project>
|
||||
implements ProjectService{
|
||||
|
||||
|
||||
@Resource
|
||||
private CommonService commonService;
|
||||
|
||||
|
||||
@Resource
|
||||
private ProjectService projectService;
|
||||
|
||||
|
||||
@Resource
|
||||
private ProjectCommissionService projectCommissionService;
|
||||
|
||||
|
||||
/**
|
||||
* 获取查询条件
|
||||
*/
|
||||
@ -36,6 +65,49 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project>
|
||||
queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
|
||||
return queryWrapper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 小程序用户查看项目列表
|
||||
* @return 项目列表
|
||||
*/
|
||||
@Override
|
||||
public List<ProjectCardVO> queryProjectCardList(HttpServletRequest request) {
|
||||
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
// 获取项目明细抽佣列表
|
||||
List<ProjectCommission> projectCommissionList = commonService.findByFieldEqTargetField(ProjectCommission::getUserId, userId, projectCommissionService);
|
||||
// 封装Map集合(键:项目id, 值:项目总价)
|
||||
Map<Long, BigDecimal> projectPriceMap = new HashMap<>();
|
||||
for (ProjectCommission projectCommission : projectCommissionList) {
|
||||
Long projectId = projectCommission.getProjectId();
|
||||
BigDecimal projectPrice = projectPriceMap.get(projectId);
|
||||
if (projectPrice == null) {
|
||||
projectPrice = projectCommission.getMyUnitPrice();
|
||||
} else {
|
||||
projectPrice = projectPrice.add(projectCommission.getMyUnitPrice());
|
||||
}
|
||||
projectPriceMap.put(projectId, projectPrice);
|
||||
}
|
||||
List<Project> projectList = commonService.findByFieldEqTargetField(Project::getIsShelves, 1, projectService);
|
||||
for (Project project : projectList) {
|
||||
BigDecimal projectPrice = projectPriceMap.get(project.getId());
|
||||
project.setProjectPrice(projectPrice == null ? BigDecimal.ZERO : projectPrice);
|
||||
}
|
||||
return commonService.convertList(projectList, ProjectCardVO.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* web端管理员根据id查询项目
|
||||
*/
|
||||
@Override
|
||||
public ProjectVO queryProjectById(CommonRequest commonRequest) {
|
||||
Long id = commonRequest.getId();
|
||||
Project project = projectService.getById(id);
|
||||
ThrowUtils.throwIf(project == null, ErrorCode.OPERATION_ERROR, "当前项目不存在");
|
||||
return commonService.copyProperties(project, ProjectVO.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,11 +1,17 @@
|
||||
package com.greenorange.promotion.service.project.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.greenorange.promotion.common.ErrorCode;
|
||||
import com.greenorange.promotion.exception.ThrowUtils;
|
||||
import com.greenorange.promotion.model.dto.CommonBatchRequest;
|
||||
import com.greenorange.promotion.model.entity.PromoCode;
|
||||
import com.greenorange.promotion.service.project.PromoCodeService;
|
||||
import com.greenorange.promotion.mapper.PromoCodeMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author 35880
|
||||
* @description 针对表【promo_code(推广码信息表)】的数据库操作Service实现
|
||||
@ -15,6 +21,19 @@ import org.springframework.stereotype.Service;
|
||||
public class PromoCodeServiceImpl extends ServiceImpl<PromoCodeMapper, PromoCode>
|
||||
implements PromoCodeService{
|
||||
|
||||
|
||||
/**
|
||||
* web端管理员批量删除推广码
|
||||
*/
|
||||
@Override
|
||||
public void delBatchPromoCode(CommonBatchRequest commonBatchRequest) {
|
||||
List<Long> ids = commonBatchRequest.getIds();
|
||||
LambdaQueryWrapper<PromoCode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.in(PromoCode::getId, ids).eq(PromoCode::getPromoCodeStatus, true);
|
||||
List<PromoCode> promoCodeList = this.list(lambdaQueryWrapper);
|
||||
ThrowUtils.throwIf(promoCodeList.size() > 0, ErrorCode.OPERATION_ERROR, "当前推广码正在使用中,无法删除");
|
||||
this.removeByIds(ids);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
package com.greenorange.promotion.service.settle;
|
||||
|
||||
import com.greenorange.promotion.model.dto.userAccount.UserAccountAddRequest;
|
||||
import com.greenorange.promotion.model.dto.userAccount.UserAccountUpdateRequest;
|
||||
import com.greenorange.promotion.model.entity.UserAccount;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author 35880
|
||||
@ -10,4 +13,14 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface UserAccountService extends IService<UserAccount> {
|
||||
|
||||
/**
|
||||
* 小程序端用户添加用户账户
|
||||
*/
|
||||
void addUserAccount(UserAccountAddRequest userAccountAddRequest, HttpServletRequest request);
|
||||
|
||||
|
||||
/**
|
||||
* 小程序端用户根据id修改用户账户信息
|
||||
*/
|
||||
void updateUserAccount(UserAccountUpdateRequest userAccountUpdateRequest, HttpServletRequest request);
|
||||
}
|
||||
|
@ -1,9 +1,14 @@
|
||||
package com.greenorange.promotion.service.settle.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.greenorange.promotion.model.dto.userAccount.UserAccountAddRequest;
|
||||
import com.greenorange.promotion.model.dto.userAccount.UserAccountUpdateRequest;
|
||||
import com.greenorange.promotion.model.entity.UserAccount;
|
||||
import com.greenorange.promotion.service.common.CommonService;
|
||||
import com.greenorange.promotion.service.settle.UserAccountService;
|
||||
import com.greenorange.promotion.mapper.UserAccountMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
@ -15,6 +20,33 @@ import org.springframework.stereotype.Service;
|
||||
public class UserAccountServiceImpl extends ServiceImpl<UserAccountMapper, UserAccount>
|
||||
implements UserAccountService{
|
||||
|
||||
|
||||
@Resource
|
||||
private CommonService commonService;
|
||||
|
||||
|
||||
/**
|
||||
* 小程序端用户添加用户账户
|
||||
*/
|
||||
@Override
|
||||
public void addUserAccount(UserAccountAddRequest userAccountAddRequest, HttpServletRequest request) {
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
UserAccount userAccount = commonService.copyProperties(userAccountAddRequest, UserAccount.class);
|
||||
userAccount.setUserId(userId);
|
||||
this.save(userAccount);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 小程序端用户根据id修改用户账户信息
|
||||
*/
|
||||
@Override
|
||||
public void updateUserAccount(UserAccountUpdateRequest userAccountUpdateRequest, HttpServletRequest request) {
|
||||
Long userId = (Long) request.getAttribute("userId");
|
||||
UserAccount userAccount = commonService.copyProperties(userAccountUpdateRequest, UserAccount.class);
|
||||
userAccount.setUserId(userId);
|
||||
this.updateById(userAccount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package com.greenorange.promotion;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
// 使用 JUnit5 的 SpringExtension 来集成 Spring TestContext
|
||||
@ExtendWith(SpringExtension.class)
|
||||
// 指定要启动的 Spring Boot 应用主类;若主类在默认扫描路径下,可省略 classes 属性
|
||||
@SpringBootTest(classes = GreenOrangeApplication.class)
|
||||
public class ApplicationStartupTest {
|
||||
|
||||
/**
|
||||
* 最简单的 context load 测试:
|
||||
* 如果 Spring 容器无法启动,这个测试就会失败。
|
||||
*/
|
||||
@Test
|
||||
void contextLoads() {
|
||||
// 只要能启动到这里,就证明 Spring Boot 应用上下文加载成功
|
||||
}
|
||||
}
|
@ -0,0 +1,75 @@
|
||||
package com.greenorange.promotion.junit;
|
||||
|
||||
import com.greenorange.promotion.model.dto.CommonRequest;
|
||||
import com.greenorange.promotion.model.entity.Project;
|
||||
import com.greenorange.promotion.model.vo.project.ProjectVO;
|
||||
import com.greenorange.promotion.service.common.CommonService;
|
||||
import com.greenorange.promotion.service.project.ProjectService;
|
||||
import com.greenorange.promotion.service.project.impl.ProjectServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ProjectServiceImplTest {
|
||||
|
||||
@InjectMocks
|
||||
private ProjectServiceImpl service;
|
||||
// 把真正的业务实现类注入进来
|
||||
|
||||
@Mock
|
||||
private CommonService commonService;
|
||||
// 用于 copyProperties
|
||||
|
||||
@Mock
|
||||
private ProjectService projectService;
|
||||
// 用于 getById
|
||||
|
||||
@Test
|
||||
void queryProjectById_notFound_throwsException() {
|
||||
// Arrange
|
||||
CommonRequest req = new CommonRequest();
|
||||
req.setId(10L);
|
||||
when(projectService.getById(10L)).thenReturn(null);
|
||||
|
||||
// Act & Assert
|
||||
RuntimeException ex = assertThrows(RuntimeException.class, () ->
|
||||
service.queryProjectById(req)
|
||||
);
|
||||
assertTrue(ex.getMessage().contains("当前项目不存在"));
|
||||
|
||||
// commonService.copyProperties 不应被调用
|
||||
verify(commonService, never()).copyProperties(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryProjectById_found_returnsVO() {
|
||||
// Arrange
|
||||
Long projectId = 20L;
|
||||
CommonRequest req = new CommonRequest();
|
||||
req.setId(projectId);
|
||||
|
||||
Project project = new Project();
|
||||
project.setId(projectId);
|
||||
project.setProjectName("示例项目");
|
||||
when(projectService.getById(projectId)).thenReturn(project);
|
||||
|
||||
ProjectVO vo = new ProjectVO();
|
||||
vo.setId(projectId);
|
||||
vo.setProjectName("示例项目");
|
||||
when(commonService.copyProperties(project, ProjectVO.class))
|
||||
.thenReturn(vo);
|
||||
|
||||
// Act
|
||||
ProjectVO result = service.queryProjectById(req);
|
||||
|
||||
// Assert
|
||||
assertSame(vo, result, "应返回 commonService.copyProperties 的结果");
|
||||
verify(commonService, times(1)).copyProperties(project, ProjectVO.class);
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package com.greenorange.promotion.junit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.greenorange.promotion.model.dto.CommonBatchRequest;
|
||||
import com.greenorange.promotion.model.entity.PromoCode;
|
||||
import com.greenorange.promotion.service.project.impl.PromoCodeServiceImpl;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class PromoCodeServiceImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private PromoCodeServiceImpl service;
|
||||
// Spy + InjectMocks:使用真实的 PromoCodeServiceImpl,但可以 stub 它的 list(...) 和 removeByIds(...)
|
||||
|
||||
/**
|
||||
* 当存在状态为“占用”的推广码时,应抛出异常并且不执行删除
|
||||
*/
|
||||
@Test
|
||||
void delBatchPromoCode_whenCodesInUse_shouldThrow() {
|
||||
// Arrange
|
||||
List<Long> ids = Arrays.asList(1L, 2L, 3L);
|
||||
CommonBatchRequest req = new CommonBatchRequest();
|
||||
req.setIds(ids);
|
||||
|
||||
// 模拟 list(...) 返回一个非空列表,表示有正在使用的推广码
|
||||
PromoCode inUse = new PromoCode();
|
||||
inUse.setId(2L);
|
||||
inUse.setPromoCodeStatus(true);
|
||||
doReturn(Collections.singletonList(inUse))
|
||||
.when(service).list(any(LambdaQueryWrapper.class));
|
||||
|
||||
// Act & Assert
|
||||
RuntimeException ex = assertThrows(RuntimeException.class,
|
||||
() -> service.delBatchPromoCode(req));
|
||||
assertTrue(ex.getMessage().contains("当前推广码正在使用中"));
|
||||
|
||||
// 验证 removeByIds(...) 从未被调用
|
||||
verify(service, never()).removeByIds(anyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 当所有推广码都未被占用时,应正常调用 removeByIds 删除
|
||||
*/
|
||||
@Test
|
||||
void delBatchPromoCode_whenNoCodesInUse_shouldRemove() {
|
||||
// Arrange
|
||||
List<Long> ids = Arrays.asList(4L, 5L);
|
||||
CommonBatchRequest req = new CommonBatchRequest();
|
||||
req.setIds(ids);
|
||||
|
||||
// 模拟 list(...) 返回空列表,表示无任何占用的推广码
|
||||
doReturn(Collections.emptyList())
|
||||
.when(service).list(any(LambdaQueryWrapper.class));
|
||||
|
||||
// 模拟 removeByIds(...) 返回 true,表示删除成功
|
||||
doReturn(true).when(service).removeByIds(ids);
|
||||
|
||||
// Act
|
||||
service.delBatchPromoCode(req);
|
||||
|
||||
// Assert
|
||||
// 验证 removeByIds(...) 被调用一次,且参数正是传入的 ids
|
||||
verify(service, times(1)).removeByIds(ids);
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.greenorange.promotion.junit;
|
||||
|
||||
import com.greenorange.promotion.model.dto.userAccount.UserAccountUpdateRequest;
|
||||
import com.greenorange.promotion.model.entity.UserAccount;
|
||||
import com.greenorange.promotion.service.common.CommonService;
|
||||
import com.greenorange.promotion.service.settle.impl.UserAccountServiceImpl;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserAccountServiceImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private UserAccountServiceImpl userAccountService;
|
||||
// Spy + InjectMocks:用真实的 serviceImpl,但可以对它的方法做部分 stub
|
||||
|
||||
@Mock
|
||||
private CommonService commonService;
|
||||
// Mock CommonService,用于模拟 copyProperties
|
||||
|
||||
@Mock
|
||||
private HttpServletRequest request;
|
||||
// Mock HttpServletRequest,用于模拟获取 userId
|
||||
|
||||
@Test
|
||||
void updateUserAccount_shouldCopyProperties_setUserId_andUpdateById() {
|
||||
// --- Arrange 准备阶段 ---
|
||||
Long userId = 456L;
|
||||
// 模拟从 request 中拿到当前登录用户 ID
|
||||
when(request.getAttribute("userId")).thenReturn(userId);
|
||||
|
||||
// 构造更新请求 DTO,并设置要更新的账户 ID
|
||||
UserAccountUpdateRequest req = new UserAccountUpdateRequest();
|
||||
req.setId(99L);
|
||||
req.setCardHolder("李四");
|
||||
req.setIdCardNumber("110101199002022345");
|
||||
req.setPhoneNumber("15900001111");
|
||||
req.setBankCardNumber("6222020202020202");
|
||||
req.setOpenBank("中国农业银行");
|
||||
|
||||
// 准备一个空实体,模拟 commonService.copyProperties 拷贝结果
|
||||
UserAccount stubEntity = new UserAccount();
|
||||
// 假设 copyProperties 会拷贝所有字段,包括 id
|
||||
stubEntity.setId(req.getId());
|
||||
stubEntity.setCardHolder(req.getCardHolder());
|
||||
stubEntity.setIdCardNumber(req.getIdCardNumber());
|
||||
stubEntity.setPhoneNumber(req.getPhoneNumber());
|
||||
stubEntity.setBankCardNumber(req.getBankCardNumber());
|
||||
stubEntity.setOpenBank(req.getOpenBank());
|
||||
// stub copyProperties 返回我们准备的 stubEntity
|
||||
when(commonService.copyProperties(req, UserAccount.class))
|
||||
.thenReturn(stubEntity);
|
||||
|
||||
// 对 Spy 的 updateById(...) 方法做 stub,避免走到 MyBatis-Plus 真逻辑
|
||||
doReturn(true).when(userAccountService).updateById(any(UserAccount.class));
|
||||
|
||||
// --- Act 执行阶段 ---
|
||||
userAccountService.updateUserAccount(req, request);
|
||||
// 方法内部执行顺序:
|
||||
// 1. 取 request.getAttribute("userId") -> 456L
|
||||
// 2. commonService.copyProperties(req, UserAccount.class) -> stubEntity
|
||||
// 3. stubEntity.setUserId(456L)
|
||||
// 4. 调用 updateById(stubEntity)
|
||||
|
||||
// --- Assert 验证阶段 ---
|
||||
// 捕获 updateById 调用时传入的参数
|
||||
ArgumentCaptor<UserAccount> captor = ArgumentCaptor.forClass(UserAccount.class);
|
||||
verify(userAccountService).updateById(captor.capture());
|
||||
UserAccount updated = captor.getValue();
|
||||
|
||||
// 验证传给 updateById 的正是 stubEntity 对象
|
||||
assertSame(stubEntity, updated, "应该传入同一个 stubEntity 实例");
|
||||
|
||||
// 验证 userId 已正确赋值
|
||||
assertEquals(userId, updated.getUserId(), "userId 应该从 request 中取出并赋值");
|
||||
|
||||
// 验证其他字段都被 copyProperties 拷贝过来,包括账户 ID
|
||||
assertEquals(req.getId(), updated.getId(), "账户 ID 应保持一致");
|
||||
assertEquals("李四", updated.getCardHolder(), "持卡人应一致");
|
||||
assertEquals("110101199002022345", updated.getIdCardNumber(), "身份证号应一致");
|
||||
assertEquals("15900001111", updated.getPhoneNumber(), "手机号应一致");
|
||||
assertEquals("6222020202020202", updated.getBankCardNumber(),"银行卡号应一致");
|
||||
assertEquals("中国农业银行", updated.getOpenBank(), "开户银行应一致");
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.greenorange.promotion.junit;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.greenorange.promotion.model.dto.userInfo.UserInfoMiniPasswordLoginRequest;
|
||||
import com.greenorange.promotion.model.entity.UserInfo;
|
||||
import com.greenorange.promotion.service.userInfo.impl.UserInfoServiceImpl;
|
||||
import com.greenorange.promotion.utils.JWTUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.*;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserInfoServiceImplTest {
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
private UserInfoServiceImpl userService; // 真实的 ServiceImpl,部分方法用 spy
|
||||
|
||||
@Mock
|
||||
private JWTUtils jwtUtils; // 用来生成 token 的工具
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// MockitoAnnotations.openMocks(this); // @ExtendWith 已自动初始化
|
||||
}
|
||||
|
||||
private UserInfoMiniPasswordLoginRequest buildRequest(String phone, String pwd) {
|
||||
UserInfoMiniPasswordLoginRequest req = new UserInfoMiniPasswordLoginRequest();
|
||||
req.setPhoneNumber(phone);
|
||||
req.setUserPassword(pwd);
|
||||
return req;
|
||||
}
|
||||
|
||||
/** 1. 手机号格式无效,应直接抛参数错误 */
|
||||
@Test
|
||||
void givenInvalidPhone_whenLoginByPwd_thenThrow() {
|
||||
UserInfoMiniPasswordLoginRequest req = buildRequest("not-a-phone", "whatever");
|
||||
assertThrows(RuntimeException.class, () -> userService.userInfoMiniLoginByPwd(req));
|
||||
}
|
||||
|
||||
/** 2. 手机号未注册,应抛操作错误 */
|
||||
@Test
|
||||
void givenUnregisteredPhone_whenLoginByPwd_thenThrow() {
|
||||
// stub 第一次 getOne(...) 返回 null
|
||||
doReturn(null)
|
||||
.when(userService).getOne(any(LambdaQueryWrapper.class));
|
||||
|
||||
UserInfoMiniPasswordLoginRequest req = buildRequest("13812345678", "pwd");
|
||||
assertThrows(RuntimeException.class, () -> userService.userInfoMiniLoginByPwd(req));
|
||||
}
|
||||
|
||||
/** 3. 密码不正确,应抛操作错误 */
|
||||
@Test
|
||||
void givenWrongPassword_whenLoginByPwd_thenThrow() {
|
||||
UserInfo dummy = new UserInfo();
|
||||
dummy.setPhoneNumber("13812345678");
|
||||
dummy.setUserPassword("rightPwd");
|
||||
|
||||
// stub 第一次 getOne(...) 返回非 null(手机号存在)
|
||||
// stub 第二次 getOne(...) 返回 null(密码校验失败)
|
||||
doReturn(dummy, null)
|
||||
.when(userService).getOne(any(LambdaQueryWrapper.class));
|
||||
|
||||
UserInfoMiniPasswordLoginRequest req = buildRequest("13812345678", "wrongPwd");
|
||||
assertThrows(RuntimeException.class, () -> userService.userInfoMiniLoginByPwd(req));
|
||||
}
|
||||
|
||||
/** 4. 成功场景:正确手机号 + 密码,返回 token,并验证 jwtUtils 调用 */
|
||||
@Test
|
||||
void givenValidCredentials_whenLoginByPwd_thenReturnToken() {
|
||||
UserInfo dummy = new UserInfo();
|
||||
dummy.setPhoneNumber("13812345678");
|
||||
dummy.setUserPassword("rightPwd");
|
||||
|
||||
// stub getOne(...) 两次都返回同一个 dummy(表示手机号存在且密码正确)
|
||||
doReturn(dummy, dummy)
|
||||
.when(userService).getOne(any(LambdaQueryWrapper.class));
|
||||
|
||||
// stub jwtUtils.generateToken(...)
|
||||
String expectedToken = "jwt-token-xyz";
|
||||
when(jwtUtils.generateToken(anyMap())).thenReturn(expectedToken);
|
||||
|
||||
UserInfoMiniPasswordLoginRequest req = buildRequest("13812345678", "rightPwd");
|
||||
String token = userService.userInfoMiniLoginByPwd(req);
|
||||
|
||||
assertEquals(expectedToken, token);
|
||||
|
||||
// 验证 payload 内容正确
|
||||
ArgumentCaptor<Map<String, String>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
verify(jwtUtils, times(1)).generateToken(captor.capture());
|
||||
Map<String, String> payload = captor.getValue();
|
||||
assertEquals("13812345678", payload.get("userAccount"));
|
||||
assertEquals("rightPwd", payload.get("userPassword"));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user