Merge remote-tracking branch 'origin/dev' into dev

# Conflicts:
#	src/main/java/com/gxwebsoft/shop/dto/OrderCreateRequest.java
#	src/main/java/com/gxwebsoft/shop/service/OrderBusinessService.java
This commit is contained in:
2025-08-09 14:46:00 +08:00
149 changed files with 6425 additions and 5835 deletions

View File

@@ -0,0 +1,56 @@
package com.gxwebsoft.bszx;
import com.gxwebsoft.bszx.service.BszxPayService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import javax.annotation.Resource;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.*;
/**
* 百色中学订单总金额统计测试
*
* @author 科技小王子
* @since 2025-07-31
*/
@SpringBootTest
@ActiveProfiles("test")
public class BszxOrderTotalTest {
@Resource
private BszxPayService bszxPayService;
@Test
void testBszxOrderTotal() {
// 测试百色中学订单总金额统计
BigDecimal total = bszxPayService.total();
// 验证返回值不为null
assertNotNull(total, "百色中学订单总金额不应该为null");
// 验证返回值大于等于0
assertTrue(total.compareTo(BigDecimal.ZERO) >= 0, "百色中学订单总金额应该大于等于0");
System.out.println("百色中学订单总金额统计结果:" + total);
}
@Test
void testBszxOrderTotalPerformance() {
// 测试性能
long startTime = System.currentTimeMillis();
BigDecimal total = bszxPayService.total();
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("百色中学订单总金额统计耗时:" + duration + "ms");
System.out.println("统计结果:" + total);
// 验证查询时间在合理范围内小于5秒
assertTrue(duration < 5000, "查询时间应该在5秒以内");
}
}

View File

@@ -20,9 +20,9 @@ public class ShopGenerator {
// 输出目录
private static final String OUTPUT_DIR = "/src/main/java";
// Vue文件输出位置
private static final String OUTPUT_LOCATION_VUE = "/Users/gxwebsoft/VUE/shop";
private static final String OUTPUT_LOCATION_VUE = "/Users/gxwebsoft/VUE/mp-vue";
// Vue文件输出目录
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/APP/shop";
private static final String OUTPUT_LOCATION_UNIAPP = "/Users/gxwebsoft/VUE/template-10550";
// Vue文件输出目录
private static final String OUTPUT_DIR_VUE = "/src";
// 作者名称
@@ -30,7 +30,7 @@ public class ShopGenerator {
// 是否在xml中添加二级缓存配置
private static final boolean ENABLE_CACHE = false;
// 数据库连接配置
private static final String DB_URL = "jdbc:mysql://47.119.165.234:3308/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
private static final String DB_URL = "jdbc:mysql://1Panel-mysql-Bqdt:3306/modules?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8";
private static final String DB_DRIVER = "com.mysql.cj.jdbc.Driver";
private static final String DB_USERNAME = "modules";
private static final String DB_PASSWORD = "8YdLnk7KsPAyDXGA";

View File

@@ -0,0 +1,38 @@
package com.gxwebsoft.house.util;
/**
* SortSceneUtil手动测试类
* 用于验证URL解码功能
*
* @author 科技小王子
* @since 2025-08-04
*/
public class SortSceneUtilManualTest {
public static void main(String[] args) {
// 测试URL编码的参数
String urlEncoded = "%E4%BB%B7%E6%A0%BC(%E4%BD%8E-%E9%AB%98)";
System.out.println("原始URL编码参数: " + urlEncoded);
String result = SortSceneUtil.normalizeSortScene(urlEncoded);
System.out.println("标准化后的参数: " + result);
System.out.println("是否为价格升序: " + SortSceneUtil.isPriceAsc(urlEncoded));
// 测试其他格式
String[] testCases = {
"价格(低-高)",
"价格(高-低)",
"%E4%BB%B7%E6%A0%BC(%E9%AB%98-%E4%BD%8E)",
"最新发布",
"综合排序",
"面积(小-大)",
"面积(大-小)"
};
System.out.println("\n=== 测试各种排序场景 ===");
for (String testCase : testCases) {
String normalized = SortSceneUtil.normalizeSortScene(testCase);
System.out.println("输入: " + testCase + " -> 输出: " + normalized);
}
}
}

View File

@@ -0,0 +1,63 @@
package com.gxwebsoft.house.util;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* SortSceneUtil测试类
*
* @author 科技小王子
* @since 2025-08-04
*/
public class SortSceneUtilTest {
@Test
public void testNormalizeSortScene() {
// 测试URL编码的参数
String urlEncoded = "%E4%BB%B7%E6%A0%BC(%E4%BD%8E-%E9%AB%98)";
String result = SortSceneUtil.normalizeSortScene(urlEncoded);
assertEquals("价格(低-高)", result);
// 测试已解码的参数
String decoded = "价格(低-高)";
result = SortSceneUtil.normalizeSortScene(decoded);
assertEquals("价格(低-高)", result);
// 测试空值
result = SortSceneUtil.normalizeSortScene(null);
assertNull(result);
result = SortSceneUtil.normalizeSortScene("");
assertNull(result);
result = SortSceneUtil.normalizeSortScene(" ");
assertNull(result);
}
@Test
public void testIsPriceAsc() {
assertTrue(SortSceneUtil.isPriceAsc("价格(低-高)"));
assertTrue(SortSceneUtil.isPriceAsc("%E4%BB%B7%E6%A0%BC(%E4%BD%8E-%E9%AB%98)"));
assertFalse(SortSceneUtil.isPriceAsc("价格(高-低)"));
assertFalse(SortSceneUtil.isPriceAsc("最新发布"));
}
@Test
public void testIsPriceDesc() {
assertTrue(SortSceneUtil.isPriceDesc("价格(高-低)"));
assertFalse(SortSceneUtil.isPriceDesc("价格(低-高)"));
assertFalse(SortSceneUtil.isPriceDesc("最新发布"));
}
@Test
public void testIsLatest() {
assertTrue(SortSceneUtil.isLatest("最新发布"));
assertFalse(SortSceneUtil.isLatest("价格(低-高)"));
}
@Test
public void testIsComprehensive() {
assertTrue(SortSceneUtil.isComprehensive("综合排序"));
assertFalse(SortSceneUtil.isComprehensive("价格(低-高)"));
}
}

View File

@@ -0,0 +1,174 @@
package com.gxwebsoft.shop;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopGoodsSku;
import com.gxwebsoft.shop.service.OrderBusinessService;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopGoodsSkuService;
import org.junit.jupiter.api.BeforeEach;
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 java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
/**
* 多规格订单测试类
*
* @author 科技小王子
* @since 2025-07-30
*/
@ExtendWith(MockitoExtension.class)
public class MultiSpecOrderTest {
@Mock
private ShopGoodsService shopGoodsService;
@Mock
private ShopGoodsSkuService shopGoodsSkuService;
@InjectMocks
private OrderBusinessService orderBusinessService;
private User testUser;
private ShopGoods testGoods;
private ShopGoodsSku testSku;
@BeforeEach
void setUp() {
// 创建测试用户
testUser = new User();
testUser.setUserId(1);
testUser.setTenantId(1);
testUser.setOpenid("test_openid");
testUser.setPhone("13800138000");
// 创建测试商品
testGoods = new ShopGoods();
testGoods.setGoodsId(1);
testGoods.setName("测试商品");
testGoods.setPrice(new BigDecimal("100.00"));
testGoods.setStock(50);
testGoods.setStatus(0); // 正常状态
testGoods.setImage("test.jpg");
// 创建测试SKU
testSku = new ShopGoodsSku();
testSku.setId(1);
testSku.setGoodsId(1);
testSku.setPrice(new BigDecimal("120.00"));
testSku.setStock(20);
testSku.setStatus(0); // 正常状态
testSku.setSku("颜色:红色|尺寸:L");
testSku.setImage("sku_test.jpg");
}
@Test
void testCreateOrderWithSingleSpec() {
// 测试单规格商品下单
when(shopGoodsService.getById(1)).thenReturn(testGoods);
OrderCreateRequest request = createOrderRequest(false);
// 这里需要mock其他依赖服务实际测试中需要完整的Spring上下文
// 此测试主要验证多规格逻辑的正确性
assertNotNull(request);
assertEquals(1, request.getGoodsItems().size());
assertNull(request.getGoodsItems().get(0).getSkuId());
}
@Test
void testCreateOrderWithMultiSpec() {
// 测试多规格商品下单
when(shopGoodsService.getById(1)).thenReturn(testGoods);
when(shopGoodsSkuService.getById(1)).thenReturn(testSku);
OrderCreateRequest request = createOrderRequest(true);
assertNotNull(request);
assertEquals(1, request.getGoodsItems().size());
assertEquals(Integer.valueOf(1), request.getGoodsItems().get(0).getSkuId());
assertEquals("颜色:红色|尺寸:L", request.getGoodsItems().get(0).getSpecInfo());
}
@Test
void testSkuValidation() {
// 测试SKU验证逻辑
when(shopGoodsService.getById(1)).thenReturn(testGoods);
// 测试SKU不存在的情况
when(shopGoodsSkuService.getById(999)).thenReturn(null);
OrderCreateRequest request = createOrderRequest(true);
request.getGoodsItems().get(0).setSkuId(999); // 不存在的SKU ID
// 在实际测试中这里应该抛出BusinessException
// assertThrows(BusinessException.class, () -> orderBusinessService.createOrder(request, testUser));
}
@Test
void testStockValidation() {
// 测试库存验证
testSku.setStock(1); // 设置库存为1
when(shopGoodsService.getById(1)).thenReturn(testGoods);
when(shopGoodsSkuService.getById(1)).thenReturn(testSku);
OrderCreateRequest request = createOrderRequest(true);
request.getGoodsItems().get(0).setQuantity(5); // 购买数量超过库存
// 在实际测试中这里应该抛出BusinessException
// assertThrows(BusinessException.class, () -> orderBusinessService.createOrder(request, testUser));
}
@Test
void testPriceCalculation() {
// 测试价格计算
when(shopGoodsService.getById(1)).thenReturn(testGoods);
when(shopGoodsSkuService.getById(1)).thenReturn(testSku);
// 多规格商品应该使用SKU价格120.00而不是商品价格100.00
OrderCreateRequest request = createOrderRequest(true);
request.getGoodsItems().get(0).setQuantity(2);
// 期望总价格 = SKU价格(120.00) * 数量(2) = 240.00
BigDecimal expectedTotal = new BigDecimal("240.00");
request.setTotalPrice(expectedTotal);
assertEquals(expectedTotal, request.getTotalPrice());
}
/**
* 创建订单请求对象
*/
private OrderCreateRequest createOrderRequest(boolean withSku) {
OrderCreateRequest request = new OrderCreateRequest();
request.setType(0);
request.setTotalPrice(new BigDecimal("100.00"));
request.setPayPrice(new BigDecimal("100.00"));
request.setTotalNum(1);
request.setTenantId(1);
OrderCreateRequest.OrderGoodsItem item = new OrderCreateRequest.OrderGoodsItem();
item.setGoodsId(1);
item.setQuantity(1);
if (withSku) {
item.setSkuId(1);
item.setSpecInfo("颜色:红色|尺寸:L");
}
request.setGoodsItems(Arrays.asList(item));
return request;
}
}

View File

@@ -0,0 +1,170 @@
package com.gxwebsoft.shop;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.entity.ShopOrderGoods;
import com.gxwebsoft.shop.service.OrderBusinessService;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import org.junit.jupiter.api.BeforeEach;
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 java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* 订单业务服务测试类
*
* @author 科技小王子
* @since 2025-01-26
*/
@ExtendWith(MockitoExtension.class)
public class OrderBusinessServiceTest {
@Mock
private ShopOrderService shopOrderService;
@Mock
private ShopOrderGoodsService shopOrderGoodsService;
@Mock
private ShopGoodsService shopGoodsService;
@InjectMocks
private OrderBusinessService orderBusinessService;
private User testUser;
private OrderCreateRequest testRequest;
private ShopGoods testGoods;
@BeforeEach
void setUp() {
// 准备测试用户
testUser = new User();
testUser.setUserId(1);
testUser.setOpenid("test_openid");
testUser.setPhone("13800138000");
// 准备测试商品
testGoods = new ShopGoods();
testGoods.setGoodsId(10018);
testGoods.setName("科技小王子大米年卡套餐2.5kg");
testGoods.setPrice(new BigDecimal("99.00"));
testGoods.setImage("test_image.jpg");
// 准备测试订单请求
testRequest = new OrderCreateRequest();
testRequest.setType(0);
testRequest.setTotalPrice(new BigDecimal("99.00"));
testRequest.setPayPrice(new BigDecimal("99.00"));
testRequest.setTotalNum(1);
testRequest.setPayType(1);
testRequest.setTenantId(1);
testRequest.setAddressId(10832);
testRequest.setComments("科技小王子大米年卡套餐2.5kg");
testRequest.setDeliveryType(0);
// 准备商品项列表
OrderCreateRequest.OrderGoodsItem goodsItem = new OrderCreateRequest.OrderGoodsItem();
goodsItem.setGoodsId(10018);
goodsItem.setQuantity(1);
goodsItem.setPayType(1);
testRequest.setGoodsItems(Arrays.asList(goodsItem));
}
@Test
void testCreateOrderWithGoods() {
// Mock 商品查询
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
// Mock 订单保存
when(shopOrderService.save(any(ShopOrder.class))).thenAnswer(invocation -> {
ShopOrder order = invocation.getArgument(0);
order.setOrderId(1); // 模拟数据库生成的ID
return true;
});
// Mock 订单商品批量保存
when(shopOrderGoodsService.saveBatch(anyList())).thenReturn(true);
// Mock 微信支付订单创建
HashMap<String, String> wxOrderInfo = new HashMap<>();
wxOrderInfo.put("prepay_id", "test_prepay_id");
when(shopOrderService.createWxOrder(any(ShopOrder.class))).thenReturn(wxOrderInfo);
// 执行测试
Map<String, String> result = orderBusinessService.createOrder(testRequest, testUser);
// 验证结果
assert result != null;
assert result.containsKey("prepay_id");
// 验证方法调用
verify(shopGoodsService, times(1)).getById(10018);
verify(shopOrderService, times(1)).save(any(ShopOrder.class));
verify(shopOrderGoodsService, times(1)).saveBatch(anyList());
verify(shopOrderService, times(1)).createWxOrder(any(ShopOrder.class));
}
@Test
void testCreateOrderWithMultipleGoods() {
// 准备多个商品项
OrderCreateRequest.OrderGoodsItem goodsItem1 = new OrderCreateRequest.OrderGoodsItem();
goodsItem1.setGoodsId(10018);
goodsItem1.setQuantity(1);
goodsItem1.setPayType(1);
OrderCreateRequest.OrderGoodsItem goodsItem2 = new OrderCreateRequest.OrderGoodsItem();
goodsItem2.setGoodsId(10019);
goodsItem2.setQuantity(2);
goodsItem2.setPayType(1);
testRequest.setGoodsItems(Arrays.asList(goodsItem1, goodsItem2));
testRequest.setTotalPrice(new BigDecimal("297.00")); // 99 + 99*2
// Mock 商品查询
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
ShopGoods testGoods2 = new ShopGoods();
testGoods2.setGoodsId(10019);
testGoods2.setName("测试商品2");
testGoods2.setPrice(new BigDecimal("99.00"));
testGoods2.setImage("test_image2.jpg");
when(shopGoodsService.getById(10019)).thenReturn(testGoods2);
// Mock 其他服务
when(shopOrderService.save(any(ShopOrder.class))).thenAnswer(invocation -> {
ShopOrder order = invocation.getArgument(0);
order.setOrderId(1);
return true;
});
when(shopOrderGoodsService.saveBatch(anyList())).thenReturn(true);
when(shopOrderService.createWxOrder(any(ShopOrder.class))).thenReturn(new HashMap<>());
// 执行测试
orderBusinessService.createOrder(testRequest, testUser);
// 验证商品查询次数
verify(shopGoodsService, times(1)).getById(10018);
verify(shopGoodsService, times(1)).getById(10019);
// 验证保存的商品项数量
verify(shopOrderGoodsService, times(1)).saveBatch(argThat(list ->
((List<ShopOrderGoods>) list).size() == 2
));
}
}

View File

@@ -0,0 +1,56 @@
package com.gxwebsoft.shop;
import com.gxwebsoft.shop.service.ShopOrderService;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import javax.annotation.Resource;
import java.math.BigDecimal;
import static org.junit.jupiter.api.Assertions.*;
/**
* 订单总金额统计测试
*
* @author 科技小王子
* @since 2025-07-30
*/
@SpringBootTest
@ActiveProfiles("test")
public class OrderTotalTest {
@Resource
private ShopOrderService shopOrderService;
@Test
void testOrderTotal() {
// 测试订单总金额统计
BigDecimal total = shopOrderService.total();
// 验证返回值不为null
assertNotNull(total, "订单总金额不应该为null");
// 验证返回值大于等于0
assertTrue(total.compareTo(BigDecimal.ZERO) >= 0, "订单总金额应该大于等于0");
System.out.println("订单总金额统计结果:" + total);
}
@Test
void testOrderTotalPerformance() {
// 测试性能
long startTime = System.currentTimeMillis();
BigDecimal total = shopOrderService.total();
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("订单总金额统计耗时:" + duration + "ms");
System.out.println("统计结果:" + total);
// 验证查询时间在合理范围内小于5秒
assertTrue(duration < 5000, "查询时间应该在5秒以内");
}
}

View File

@@ -0,0 +1,315 @@
package com.gxwebsoft.shop;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.shop.config.OrderConfigProperties;
import com.gxwebsoft.shop.dto.OrderCreateRequest;
import com.gxwebsoft.shop.entity.ShopGoods;
import com.gxwebsoft.shop.entity.ShopOrder;
import com.gxwebsoft.shop.service.OrderBusinessService;
import com.gxwebsoft.shop.service.ShopGoodsService;
import com.gxwebsoft.shop.service.ShopOrderGoodsService;
import com.gxwebsoft.shop.service.ShopOrderService;
import org.junit.jupiter.api.BeforeEach;
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 java.math.BigDecimal;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* 订单验证测试类
* 测试商品信息后台验证逻辑
*/
@ExtendWith(MockitoExtension.class)
class OrderValidationTest {
@Mock
private ShopOrderService shopOrderService;
@Mock
private ShopOrderGoodsService shopOrderGoodsService;
@Mock
private ShopGoodsService shopGoodsService;
@Mock
private OrderConfigProperties orderConfig;
@InjectMocks
private OrderBusinessService orderBusinessService;
private User testUser;
private OrderCreateRequest testRequest;
private ShopGoods testGoods;
@BeforeEach
void setUp() {
// 准备测试用户
testUser = new User();
testUser.setUserId(1);
testUser.setNickname("测试用户");
testUser.setPhone("13800138000");
// 准备测试商品
testGoods = new ShopGoods();
testGoods.setGoodsId(10018);
testGoods.setName("测试商品");
testGoods.setPrice(new BigDecimal("99.00"));
testGoods.setStatus(0); // 上架状态
testGoods.setStock(100); // 库存100
testGoods.setCanBuyNumber(10); // 最大购买数量10
testGoods.setCode("TEST001");
// 准备测试订单请求
testRequest = new OrderCreateRequest();
testRequest.setType(0);
testRequest.setTitle("测试订单");
testRequest.setTotalPrice(new BigDecimal("99.00"));
testRequest.setTenantId(1);
// 准备商品项
OrderCreateRequest.OrderGoodsItem goodsItem = new OrderCreateRequest.OrderGoodsItem();
goodsItem.setGoodsId(10018);
goodsItem.setQuantity(1);
testRequest.setGoodsItems(Arrays.asList(goodsItem));
}
@Test
void testValidateOrderRequest_Success() {
// Mock 商品查询
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
when(orderConfig.getTenantRule(1)).thenReturn(null);
// 执行验证 - 应该成功
assertDoesNotThrow(() -> {
// 使用反射调用私有方法进行测试
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 验证总金额被正确设置
assertEquals(new BigDecimal("99.00"), testRequest.getTotalPrice());
}
@Test
void testValidateOrderRequest_GoodsNotFound() {
// Mock 商品不存在
when(shopGoodsService.getById(10018)).thenReturn(null);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("商品不存在"));
}
@Test
void testValidateOrderRequest_GoodsOffShelf() {
// 设置商品为下架状态
testGoods.setStatus(1);
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("商品已下架"));
}
@Test
void testValidateOrderRequest_InsufficientStock() {
// 设置库存不足
testGoods.setStock(0);
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("商品库存不足"));
}
@Test
void testValidateOrderRequest_ExceedBuyLimit() {
// 设置购买数量超过限制
testRequest.getGoodsItems().get(0).setQuantity(15); // 超过最大购买数量10
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("购买数量超过限制"));
}
@Test
void testValidateOrderRequest_PriceCalculation() {
// 设置多个商品项
OrderCreateRequest.OrderGoodsItem goodsItem1 = new OrderCreateRequest.OrderGoodsItem();
goodsItem1.setGoodsId(10018);
goodsItem1.setQuantity(2);
OrderCreateRequest.OrderGoodsItem goodsItem2 = new OrderCreateRequest.OrderGoodsItem();
goodsItem2.setGoodsId(10019);
goodsItem2.setQuantity(1);
testRequest.setGoodsItems(Arrays.asList(goodsItem1, goodsItem2));
testRequest.setTotalPrice(new BigDecimal("297.00")); // 99*2 + 99*1
// 准备第二个商品
ShopGoods testGoods2 = new ShopGoods();
testGoods2.setGoodsId(10019);
testGoods2.setName("测试商品2");
testGoods2.setPrice(new BigDecimal("99.00"));
testGoods2.setStatus(0);
testGoods2.setStock(100);
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
when(shopGoodsService.getById(10019)).thenReturn(testGoods2);
when(orderConfig.getTenantRule(1)).thenReturn(null);
// 执行验证 - 应该成功
assertDoesNotThrow(() -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 验证总金额计算正确
assertEquals(new BigDecimal("297.00"), testRequest.getTotalPrice());
}
@Test
void testValidateOrderRequest_PriceDiscrepancy() {
// 设置前端传入的金额与后台计算不一致
testRequest.setTotalPrice(new BigDecimal("88.00")); // 错误的金额
when(shopGoodsService.getById(10018)).thenReturn(testGoods);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
java.lang.reflect.Method method = OrderBusinessService.class
.getDeclaredMethod("validateOrderRequest", OrderCreateRequest.class, User.class);
method.setAccessible(true);
method.invoke(orderBusinessService, testRequest, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("订单金额计算错误"));
}
@Test
void testBuildShopOrder_RequiredFields() throws Exception {
// Mock 配置
OrderConfigProperties.DefaultConfig defaultConfig = new OrderConfigProperties.DefaultConfig();
defaultConfig.setDefaultComments("默认备注");
when(orderConfig.getDefaultConfig()).thenReturn(defaultConfig);
// 使用反射调用 buildShopOrder 方法
java.lang.reflect.Method buildMethod = OrderBusinessService.class
.getDeclaredMethod("buildShopOrder", OrderCreateRequest.class, User.class);
buildMethod.setAccessible(true);
ShopOrder result = (ShopOrder) buildMethod.invoke(orderBusinessService, testRequest, testUser);
// 验证必需字段都已设置
assertNotNull(result.getPayPrice(), "payPrice 不能为空");
assertNotNull(result.getPrice(), "price 不能为空");
assertNotNull(result.getReducePrice(), "reducePrice 不能为空");
assertNotNull(result.getMoney(), "money 不能为空");
assertNotNull(result.getPayStatus(), "payStatus 不能为空");
assertNotNull(result.getOrderStatus(), "orderStatus 不能为空");
assertNotNull(result.getDeliveryStatus(), "deliveryStatus 不能为空");
assertNotNull(result.getPayType(), "payType 不能为空");
// 验证默认值
assertEquals(testRequest.getTotalPrice(), result.getPayPrice());
assertEquals(testRequest.getTotalPrice(), result.getPrice());
assertEquals(BigDecimal.ZERO, result.getReducePrice());
assertEquals(testRequest.getTotalPrice(), result.getMoney());
assertEquals(false, result.getPayStatus());
assertEquals(Integer.valueOf(0), result.getOrderStatus());
assertEquals(Integer.valueOf(10), result.getDeliveryStatus());
assertEquals(Integer.valueOf(1), result.getPayType());
// 验证关键字段 - 租户ID影响微信支付证书路径
assertNotNull(result.getTenantId(), "tenantId 不能为空");
assertEquals(testRequest.getTenantId(), result.getTenantId(), "tenantId 必须正确设置");
}
@Test
void testBuildShopOrder_TenantIdValidation() throws Exception {
// 创建一个新的请求对象租户ID为空
OrderCreateRequest requestWithoutTenant = new OrderCreateRequest();
requestWithoutTenant.setType(0);
requestWithoutTenant.setTitle("测试订单");
requestWithoutTenant.setTotalPrice(new BigDecimal("99.00"));
requestWithoutTenant.setTenantId(null); // 设置为空
// 准备商品项
OrderCreateRequest.OrderGoodsItem goodsItem = new OrderCreateRequest.OrderGoodsItem();
goodsItem.setGoodsId(10018);
goodsItem.setQuantity(1);
requestWithoutTenant.setGoodsItems(Arrays.asList(goodsItem));
// 使用反射调用 buildShopOrder 方法
java.lang.reflect.Method buildMethod = OrderBusinessService.class
.getDeclaredMethod("buildShopOrder", OrderCreateRequest.class, User.class);
buildMethod.setAccessible(true);
// 执行验证 - 应该抛出异常
Exception exception = assertThrows(Exception.class, () -> {
buildMethod.invoke(orderBusinessService, requestWithoutTenant, testUser);
});
// 检查是否是 InvocationTargetException 包装的 BusinessException
assertTrue(exception instanceof java.lang.reflect.InvocationTargetException);
Throwable cause = exception.getCause();
assertTrue(cause instanceof BusinessException);
assertTrue(cause.getMessage().contains("租户ID不能为空"));
}
}