Commit bc2aa78f706ca45ae1e4e715de56eb031e001d3c

Authored by YunaiV
1 parent 01d10b51

trade:创建订单接口的后端实现的单元测试 50%

Showing 12 changed files with 247 additions and 233 deletions
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java
... ... @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.convert.order;
3 3 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 4 import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
5 5 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  6 +import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
6 7 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
7 8 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
8 9 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
... ... @@ -33,7 +34,7 @@ public interface TradeOrderConvert {
33 34 @Mapping(source = "address.postCode", target = "receiverPostCode"),
34 35 @Mapping(source = "address.detailAddress", target = "receiverDetailAddress"),
35 36 })
36   - TradeOrderDO convert(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO,
  37 + TradeOrderDO convert(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO,
37 38 PriceCalculateRespDTO.Order order, AddressRespDTO address);
38 39  
39 40 @Mappings({
... ... @@ -49,10 +50,13 @@ public interface TradeOrderConvert {
49 50 TradeOrderItemDO tradeOrderItemDO = convert(orderItem, skuMap.get(orderItem.getSkuId()));
50 51 tradeOrderItemDO.setOrderId(tradeOrderDO.getId());
51 52 tradeOrderItemDO.setUserId(tradeOrderDO.getUserId());
52   - tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus());
  53 + tradeOrderItemDO.setRefundStatus(TradeOrderItemRefundStatusEnum.NONE.getStatus()).setRefundTotal(0); // 退款信息
53 54 // tradeOrderItemDO.setCommented(false);
54 55 return tradeOrderItemDO;
55 56 });
56 57 }
57 58  
  59 + @Mapping(source = "userId" , target = "userId")
  60 + PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId);
  61 +
58 62 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/price/PriceConvert.java deleted
1   -package cn.iocoder.yudao.module.trade.convert.price;
2   -
3   -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
4   -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
5   -import org.mapstruct.Mapper;
6   -import org.mapstruct.Mapping;
7   -import org.mapstruct.Mappings;
8   -import org.mapstruct.factory.Mappers;
9   -
10   -@Mapper
11   -public interface PriceConvert {
12   -
13   - PriceConvert INSTANCE = Mappers.getMapper(PriceConvert.class);
14   -
15   - @Mappings(
16   - @Mapping(source = "userId" , target = "userId")
17   - )
18   - PriceCalculateReqDTO convert(AppTradeOrderCreateReqVO createReqVO, Long userId);
19   -
20   -}
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/order/TradeOrderItemDO.java
... ... @@ -138,19 +138,19 @@ public class TradeOrderItemDO extends BaseDO {
138 138 * 枚举 {@link TradeOrderItemRefundStatusEnum}
139 139 */
140 140 private Integer refundStatus; // TODO 芋艿:可以考虑去查
141   -// // 如上字段,举个例子:
142   -// // 假设购买三个,即 stock = 3 。
143   -// // originPrice = 15
144   -// // 使用限时折扣(单品优惠)8 折,buyPrice = 12
145   -// // 开始算总的价格
146   -// // buyTotal = buyPrice * stock = 12 * 3 = 36
147   -// // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11
148   -// // presentTotal = buyTotal - discountTotal = 24 - 11 = 13
149   -// // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33
150   -// /**
151   -// * 退款总金额,单位:分 TODO
152   -// */
153   -// private Integer refundTotal;
  141 + // 如上字段,举个例子:
  142 + // 假设购买三个,即 stock = 3 。
  143 + // originPrice = 15
  144 + // 使用限时折扣(单品优惠)8 折,buyPrice = 12
  145 + // 开始算总的价格
  146 + // buyTotal = buyPrice * stock = 12 * 3 = 36
  147 + // discountTotal ,假设有满减送(分组优惠)满 20 减 10 ,并且使用优惠劵满 1.01 减 1 ,则 discountTotal = 10 + 1 = 11
  148 + // presentTotal = buyTotal - discountTotal = 24 - 11 = 13
  149 + // 最终 presentPrice = presentTotal / stock = 13 / 3 = 4.33
  150 + /**
  151 + * 退款总金额,单位:分 TODO
  152 + */
  153 + private Integer refundTotal;
154 154  
155 155 /**
156 156 * 商品属性
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderService.java
... ... @@ -14,9 +14,10 @@ public interface TradeOrderService {
14 14 * 创建交易订单
15 15 *
16 16 * @param loginUserId 登录用户
17   - * @param clientIp 用户 IP 地址
  17 + * @param userIp 用户 IP 地址
18 18 * @param createReqVO 创建交易订单请求模型
19 19 * @return 交易订单的编号
20 20 */
21   - Long createTradeOrder(Long loginUserId, String clientIp, AppTradeOrderCreateReqVO createReqVO);
  21 + Long createTradeOrder(Long loginUserId, String userIp, AppTradeOrderCreateReqVO createReqVO);
  22 +
22 23 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java
... ... @@ -18,12 +18,10 @@ import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
18 18 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
19 19 import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
20 20 import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
21   -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateReqDTO;
22 21 import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
23 22 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
24 23 import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO.Item;
25 24 import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
26   -import cn.iocoder.yudao.module.trade.convert.price.PriceConvert;
27 25 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
28 26 import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
29 27 import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
... ... @@ -82,20 +80,19 @@ public class TradeOrderServiceImpl implements TradeOrderService {
82 80  
83 81 @Override
84 82 @Transactional(rollbackFor = Exception.class)
85   - public Long createTradeOrder(Long userId, String clientIp, AppTradeOrderCreateReqVO createReqVO) {
  83 + public Long createTradeOrder(Long userId, String userIp, AppTradeOrderCreateReqVO createReqVO) {
86 84 // 商品 SKU 检查:可售状态、库存
87 85 List<ProductSkuRespDTO> skus = validateSkuSaleable(createReqVO.getItems());
88 86 // 商品 SPU 检查:可售状态
89   - List<ProductSpuRespDTO> spus = validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId));
  87 + validateSpuSaleable(convertSet(skus, ProductSkuRespDTO::getSpuId));
90 88 // 用户收件地址的校验
91 89 AddressRespDTO address = validateAddress(userId, createReqVO.getAddressId());
92 90  
93 91 // 价格计算
94   - PriceCalculateReqDTO priceCalculateReqDTO = PriceConvert.INSTANCE.convert(createReqVO, userId);
95   - PriceCalculateRespDTO priceResp = priceApi.calculatePrice(priceCalculateReqDTO);
  92 + PriceCalculateRespDTO priceResp = priceApi.calculatePrice(TradeOrderConvert.INSTANCE.convert(createReqVO, userId));
96 93  
97 94 // 插入 TradeOrderDO 订单
98   - TradeOrderDO tradeOrderDO = createTradeOrder(userId, clientIp, createReqVO, priceResp.getOrder(), address);
  95 + TradeOrderDO tradeOrderDO = createTradeOrder(userId, userIp, createReqVO, priceResp.getOrder(), address);
99 96 // 插入 TradeOrderItemDO 订单项
100 97 createTradeOrderItems(tradeOrderDO, priceResp.getOrder().getItems(), skus);
101 98  
... ... @@ -208,7 +205,7 @@ public class TradeOrderServiceImpl implements TradeOrderService {
208 205 // 校验是否存在禁用的 SPU
209 206 ProductSpuRespDTO spu = CollectionUtils.findFirst(spus,
210 207 spuDTO -> ObjectUtil.notEqual(ProductSpuStatusEnum.ENABLE.getStatus(), spuDTO.getStatus()));
211   - if (Objects.isNull(spu)) {
  208 + if (spu != null) {
212 209 throw exception(ErrorCodeConstants.ORDER_CREATE_SPU_NOT_SALE);
213 210 }
214 211 return spus;
... ... @@ -238,6 +235,9 @@ public class TradeOrderServiceImpl implements TradeOrderService {
238 235 tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
239 236 tradeOrderDO.setProductCount(getSumValue(order.getItems(), PriceCalculateRespDTO.OrderItem::getCount, Integer::sum));
240 237 tradeOrderDO.setTerminal(TerminalEnum.H5.getTerminal()); // todo 数据来源?
  238 + tradeOrderDO.setAdjustPrice(0).setPayed(false); // 支付信息
  239 + tradeOrderDO.setDeliveryStatus(false); // 物流信息
  240 + tradeOrderDO.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus()).setRefundPrice(0); // 退款信息
241 241 tradeOrderMapper.insert(tradeOrderDO);
242 242 return tradeOrderDO;
243 243 }
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java deleted
1   -package cn.iocoder.yudao.module.trade.service.order;
2   -
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
5   -import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
6   -import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
7   -import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
8   -import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
9   -import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
10   -import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
11   -import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO;
12   -import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
13   -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
14   -import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
15   -import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
16   -import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper;
17   -import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
18   -import com.google.common.collect.Lists;
19   -import org.junit.jupiter.api.Test;
20   -import org.springframework.boot.test.mock.mockito.MockBean;
21   -import org.springframework.context.annotation.Import;
22   -
23   -import javax.annotation.Resource;
24   -import java.util.Collections;
25   -
26   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomInteger;
27   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
28   -import static org.junit.jupiter.api.Assertions.assertEquals;
29   -import static org.junit.jupiter.api.Assertions.assertNotNull;
30   -import static org.mockito.ArgumentMatchers.any;
31   -import static org.mockito.Mockito.when;
32   -
33   -// TODO @芋艿: 单测的 review; 最后搞;
34   -/**
35   - * @author LeeYan9
36   - * @since 2022-09-07
37   - */
38   -@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class})
39   -class TradeOrderServiceTest extends BaseDbUnitTest {
40   -
41   -
42   - @Resource
43   - TradeOrderService tradeOrderService;
44   - @Resource
45   - TradeOrderMapper tradeOrderMapper;
46   - @Resource
47   - TradeOrderItemMapper tradeOrderItemMapper;
48   - @MockBean
49   - ProductSpuApi productSpuApi;
50   - @MockBean
51   - ProductSkuApi productSkuApi;
52   - @MockBean
53   - PriceApi priceApi;
54   - @MockBean
55   - private PayOrderApi payOrderApi;
56   -
57   - @Test
58   - void testCreateTradeOrder_success() {
59   - // mock 商品SPU数据
60   - SpuInfoRespDTO spuInfoRespDTO = randomPojo(SpuInfoRespDTO.class, spuInfo -> {
61   - spuInfo.setId(1L);
62   - spuInfo.setStatus(CommonStatusEnum.ENABLE.getStatus());
63   - });
64   - when(productSpuApi.getSpuList(Collections.singleton(1L))).thenReturn(Lists.newArrayList(spuInfoRespDTO));
65   - // mock 商品SkU数据
66   - ProductSkuRespDTO skuInfoRespDTO = randomPojo(ProductSkuRespDTO.class, skuInfo -> {
67   - skuInfo.setId(1L);
68   - skuInfo.setStatus(CommonStatusEnum.ENABLE.getStatus());
69   - skuInfo.setStock(randomInteger());
70   - skuInfo.setSpuId(1L);
71   - });
72   - when(productSkuApi.getSkuList(Collections.singleton(1L))).thenReturn(Lists.newArrayList(skuInfoRespDTO));
73   - // mock 价格信息
74   - PriceCalculateRespDTO calculateRespDTO = randomPojo(PriceCalculateRespDTO.class, priceCalculateRespDTO -> {
75   - PriceCalculateRespDTO.OrderItem item = priceCalculateRespDTO.getOrder().getItems().get(0);
76   - item.setSkuId(1L);
77   - item.setCount(2);
78   - priceCalculateRespDTO.getOrder().setItems(Collections.singletonList(item));
79   - });
80   - when(priceApi.calculatePrice(any())).thenReturn(calculateRespDTO);
81   - //mock 支付订单信息
82   - when(payOrderApi.createPayOrder(any())).thenReturn(1L);
83   -
84   - // 准备请求数据
85   - AppTradeOrderCreateReqVO tradeOrderCreateReqVO = randomPojo(AppTradeOrderCreateReqVO.class, reqVO -> {
86   - AppTradeOrderCreateReqVO.Item item = randomPojo(AppTradeOrderCreateReqVO.Item.class, o -> {
87   - o.setSkuId(1L);
88   - o.setCount(2);
89   - });
90   - reqVO.setItems(Collections.singletonList(item));
91   - });
92   - // 创建交易订单,支付订单记录
93   - Long payOrderId = tradeOrderService.createTradeOrder(1L, "127.0.0.1", tradeOrderCreateReqVO);
94   - //断言交易订单
95   - TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(TradeOrderDO::getUserId, 1L);
96   - assertNotNull(tradeOrderDO);
97   - //价格&用户
98   - assertEquals(calculateRespDTO.getOrder().getPayPrice(), tradeOrderDO.getPayPrice());
99   - assertEquals(1L, tradeOrderDO.getUserId());
100   - //断言交易订单项
101   - TradeOrderItemDO tradeOrderItemDO = tradeOrderItemMapper.selectOne(TradeOrderItemDO::getOrderId, tradeOrderDO.getId());
102   - assertNotNull(tradeOrderDO);
103   - //商品&用户
104   - assertEquals(skuInfoRespDTO.getId(), tradeOrderItemDO.getSkuId());
105   - assertEquals(1L, tradeOrderItemDO.getUserId());
106   - //价格
107   - assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice());
108   - }
109   -
110   -}
yudao-module-mall/yudao-module-trade-biz/src/main/test/resources/sql/create_tables.sql deleted
1   -/**todo cancelType 设置默认值 0?*/
2   -
3   -CREATE TABLE IF NOT EXISTS `trade_order`
4   -(
5   - `id` number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
6   - `sn` varchar(32) NOT NULL,
7   - `type` int NOT NULL,
8   - `terminal` int NOT NULL,
9   - `user_id` bigint unsigned NOT NULL,
10   - `user_ip` varchar(30) NOT NULL,
11   - `user_remark` varchar(200),
12   - `status` int NOT NULL,
13   - `product_count` int NOT NULL,
14   - `cancel_type` int DEFAULT NULL,
15   - `remark` varchar(200),
16   - `payed` bit(1) NOT NULL DEFAULT FALSE,
17   - `pay_time` datetime DEFAULT NULL,
18   - `finish_time` datetime DEFAULT NULL,
19   - `cancel_time` datetime DEFAULT NULL,
20   - `sku_original_price` int NOT NULL DEFAULT '0',
21   - `sku_promotion_price` int NOT NULL DEFAULT '0',
22   - `order_promotion_price` int NOT NULL DEFAULT '0',
23   - `delivery_price` int NOT NULL DEFAULT '0',
24   - `pay_price` int DEFAULT '0',
25   - `pay_order_id` int DEFAULT NULL,
26   - `pay_channel` int DEFAULT NULL,
27   - `delivery_type` int NOT NULL DEFAULT '1',
28   - `actual_delivery_type` int NOT NULL DEFAULT '1',
29   - `delivery_template_id` int DEFAULT NULL,
30   - `express_no` int DEFAULT NULL,
31   - `delivery_status` bit(1) NOT NULL DEFAULT FALSE,
32   - `delivery_time` datetime DEFAULT NULL,
33   - `receive_time` datetime DEFAULT NULL,
34   - `receiver_name` varchar(20) DEFAULT NULL,
35   - `receiver_mobile` varchar(20) DEFAULT NULL,
36   - `receiver_area_id` int DEFAULT NULL,
37   - `receiver_post_code` int DEFAULT NULL,
38   - `receiver_detail_address` varchar(255) DEFAULT NULL,
39   - `refund_status` int NOT NULL DEFAULT '0',
40   - `refund_price` int NOT NULL DEFAULT '0',
41   - `coupon_id` bigint unsigned DEFAULT NULL,
42   - `creator` varchar(64) DEFAULT '',
43   - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
44   - `updater` varchar(64) DEFAULT '',
45   - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
46   - `deleted` bit(1) NOT NULL DEFAULT FALSE,
47   - PRIMARY KEY ("id")
48   -);
49   -
50   -
51   -CREATE TABLE IF NOT EXISTS `trade_order_item`
52   -(
53   - `id` number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
54   - `user_id` bigint unsigned NOT NULL,
55   - `order_id` bigint unsigned NOT NULL,
56   - `spu_id` bigint unsigned NOT NULL,
57   - `sku_id` bigint unsigned NOT NULL,
58   - `properties` json DEFAULT NULL,
59   - `name` varchar(128) DEFAULT NULL,
60   - `pic_url` varchar(200) DEFAULT NULL,
61   - `count` int NOT NULL,
62   - `commented` bit(1) DEFAULT NULL,
63   - `original_price` int NOT NULL DEFAULT '0',
64   - `total_original_price` int NOT NULL DEFAULT '0',
65   - `total_promotion_price` int NOT NULL DEFAULT '0',
66   - `present_price` int NOT NULL DEFAULT '0',
67   - `total_present_price` int NOT NULL DEFAULT '0',
68   - `total_pay_price` int NOT NULL DEFAULT '0',
69   - `refund_status` int NOT NULL DEFAULT '0',
70   - `refund_total` int NOT NULL DEFAULT '0',
71   - `creator` varchar(64) DEFAULT '',
72   - `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
73   - `updater` varchar(64) DEFAULT '',
74   - `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
75   - `deleted` bit(1) DEFAULT FALSE,
76   - PRIMARY KEY ("id")
77   -);
78   -
yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.trade.service.order;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  5 +import cn.iocoder.yudao.module.member.api.address.AddressApi;
  6 +import cn.iocoder.yudao.module.member.api.address.dto.AddressRespDTO;
  7 +import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
  8 +import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
  9 +import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
  10 +import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
  11 +import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
  12 +import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
  13 +import cn.iocoder.yudao.module.promotion.api.price.PriceApi;
  14 +import cn.iocoder.yudao.module.promotion.api.price.dto.PriceCalculateRespDTO;
  15 +import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderCreateReqVO;
  16 +import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
  17 +import cn.iocoder.yudao.module.trade.dal.mysql.orderitem.TradeOrderItemMapper;
  18 +import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
  19 +import org.junit.jupiter.api.Test;
  20 +import org.springframework.boot.test.mock.mockito.MockBean;
  21 +import org.springframework.context.annotation.Import;
  22 +
  23 +import javax.annotation.Resource;
  24 +import java.util.Arrays;
  25 +
  26 +import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
  27 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  28 +import static org.junit.jupiter.api.Assertions.assertEquals;
  29 +import static org.mockito.ArgumentMatchers.argThat;
  30 +import static org.mockito.ArgumentMatchers.eq;
  31 +import static org.mockito.Mockito.when;
  32 +
  33 +/**
  34 + * {@link TradeOrderServiceImpl} 的单元测试类
  35 + *
  36 + * @author LeeYan9
  37 + * @since 2022-09-07
  38 + */
  39 +@Import({TradeOrderServiceImpl.class, TradeOrderConfig.class})
  40 +class TradeOrderServiceTest extends BaseDbUnitTest {
  41 +
  42 + @Resource
  43 + private TradeOrderServiceImpl tradeOrderService;
  44 +
  45 + @Resource
  46 + private TradeOrderMapper tradeOrderMapper;
  47 + @Resource
  48 + private TradeOrderItemMapper tradeOrderItemMapper;
  49 +
  50 + @MockBean
  51 + private ProductSpuApi productSpuApi;
  52 + @MockBean
  53 + private ProductSkuApi productSkuApi;
  54 + @MockBean
  55 + private PriceApi priceApi;
  56 + @MockBean
  57 + private PayOrderApi payOrderApi;
  58 + @MockBean
  59 + private AddressApi addressApi;
  60 +
  61 + // 1, 3 个,50 块;打折 20;总和 = 60;42;
  62 + // 2, 4 个,20 块;打折 10;总和 = 40;28;
  63 + // 优惠劵,满 100 减 30
  64 +
  65 + @Test
  66 + public void testCreateTradeOrder_success() {
  67 + // 准备参数
  68 + Long userId = 100L;
  69 + String clientIp = "127.0.0.1";
  70 + AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
  71 + .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
  72 + .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
  73 + new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
  74 + // mock 方法(商品 SKU 检查)
  75 + ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
  76 + .setPrice(50).setStock(100).setStatus(CommonStatusEnum.ENABLE.getStatus()));
  77 + ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
  78 + .setPrice(20).setStock(50).setStatus(CommonStatusEnum.ENABLE.getStatus()));
  79 + when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
  80 + // mock 方法(商品 SPU 检查)
  81 + ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
  82 + .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
  83 + ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
  84 + .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
  85 + when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
  86 + // mock 方法(用户收件地址的校验)
  87 + AddressRespDTO addressRespDTO = new AddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
  88 + .setMobile("15601691300").setAreaId(3306L).setPostCode("85757").setDetailAddress("土豆村");
  89 + when(addressApi.getAddress(eq(userId), eq(10L))).thenReturn(addressRespDTO);
  90 + // mock 方法(价格计算)
  91 + PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
  92 + .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
  93 + .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
  94 + PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
  95 + .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
  96 + .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
  97 + PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
  98 + .setOriginalPrice(230).setOrderPrice(100).setDiscountPrice(0).setCouponPrice(30)
  99 + .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
  100 + .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
  101 + when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
  102 + assertEquals(priceCalculateReqDTO.getUserId(), 100L);
  103 + assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
  104 + assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
  105 + assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
  106 + assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
  107 + assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
  108 + return true;
  109 + }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
  110 +
  111 + // 调用方法
  112 + Long tradeOrderId = tradeOrderService.createTradeOrder(userId, clientIp, reqVO);
  113 + System.out.println(tradeOrderId);
  114 +
  115 +// // mock 价格信息
  116 +// PriceCalculateRespDTO calculateRespDTO = randomPojo(PriceCalculateRespDTO.class, priceCalculateRespDTO -> {
  117 +// PriceCalculateRespDTO.OrderItem item = priceCalculateRespDTO.getOrder().getItems().get(0);
  118 +// item.setSkuId(1L);
  119 +// item.setCount(2);
  120 +// priceCalculateRespDTO.getOrder().setItems(Collections.singletonList(item));
  121 +// });
  122 +// when(priceApi.calculatePrice(any())).thenReturn(calculateRespDTO);
  123 +// //mock 支付订单信息
  124 +// when(payOrderApi.createPayOrder(any())).thenReturn(1L);
  125 +
  126 +
  127 +// // 创建交易订单,支付订单记录
  128 +// Long payOrderId = tradeOrderService.createTradeOrder(1L, "127.0.0.1", tradeOrderCreateReqVO);
  129 +// //断言交易订单
  130 +// TradeOrderDO tradeOrderDO = tradeOrderMapper.selectOne(TradeOrderDO::getUserId, 1L);
  131 +// assertNotNull(tradeOrderDO);
  132 +// //价格&用户
  133 +// assertEquals(calculateRespDTO.getOrder().getPayPrice(), tradeOrderDO.getPayPrice());
  134 +// assertEquals(1L, tradeOrderDO.getUserId());
  135 +// //断言交易订单项
  136 +// TradeOrderItemDO tradeOrderItemDO = tradeOrderItemMapper.selectOne(TradeOrderItemDO::getOrderId, tradeOrderDO.getId());
  137 +// assertNotNull(tradeOrderDO);
  138 +// //商品&用户
  139 +// assertEquals(skuInfoRespDTO.getId(), tradeOrderItemDO.getSkuId());
  140 +// assertEquals(1L, tradeOrderItemDO.getUserId());
  141 +// //价格
  142 +// assertEquals(calculateRespDTO.getOrder().getItems().get(0).getPresentPrice(), tradeOrderItemDO.getPresentPrice());
  143 + }
  144 +
  145 +}
... ...
yudao-module-mall/yudao-module-trade-biz/src/main/test/resources/application-unit-test.yaml renamed to yudao-module-mall/yudao-module-trade-biz/src/test/resources/application-unit-test.yaml
yudao-module-mall/yudao-module-trade-biz/src/main/test/resources/logback.xml renamed to yudao-module-mall/yudao-module-trade-biz/src/test/resources/logback.xml
yudao-module-mall/yudao-module-trade-biz/src/main/test/resources/sql/clean.sql renamed to yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/clean.sql
yudao-module-mall/yudao-module-trade-biz/src/test/resources/sql/create_tables.sql 0 → 100644
  1 +CREATE TABLE IF NOT EXISTS "trade_order" (
  2 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  3 + "no" varchar NOT NULL,
  4 + "type" int NOT NULL,
  5 + "terminal" int NOT NULL,
  6 + "user_id" bigint NOT NULL,
  7 + "user_ip" varchar NOT NULL,
  8 + "user_remark" varchar,
  9 + "status" int NOT NULL,
  10 + "product_count" int NOT NULL,
  11 + "cancel_type" int,
  12 + "remark" varchar,
  13 + "payed" bit NOT NULL,
  14 + "pay_time" datetime,
  15 + "finish_time" datetime,
  16 + "cancel_time" datetime,
  17 + "original_price" int NOT NULL,
  18 + "order_price" int NOT NULL,
  19 + "discount_price" int NOT NULL,
  20 + "delivery_price" int NOT NULL,
  21 + "adjust_price" int NOT NULL,
  22 + "pay_price" int NOT NULL,
  23 + "pay_order_id" int,
  24 + "pay_channel" int,
  25 + "delivery_templateid" int,
  26 + "express_no" int,
  27 + "delivery_status" bit NOT NULL,
  28 + "delivery_time" datetime,
  29 + "receive_time" datetime,
  30 + "receiver_name" varchar NOT NULL,
  31 + "receiver_mobile" varchar NOT NULL,
  32 + "receiver_area_id" int NOT NULL,
  33 + "receiver_post_code" int,
  34 + "receiver_detail_address" varchar NOT NULL,
  35 + "refund_status" int NOT NULL,
  36 + "refund_price" int NOT NULL,
  37 + "coupon_id" bigint NOT NULL,
  38 + "coupon_price" int NOT NULL,
  39 + "point_price" int NOT NULL,
  40 + "creator" varchar DEFAULT '',
  41 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  42 + "updater" varchar DEFAULT '',
  43 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  44 + "deleted" bit NOT NULL DEFAULT FALSE,
  45 + PRIMARY KEY ("id")
  46 +) COMMENT '交易订单表';
  47 +
  48 +CREATE TABLE IF NOT EXISTS "trade_order_item" (
  49 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  50 + "user_id" bigint NOT NULL,
  51 + "order_id" bigint NOT NULL,
  52 + "spu_id" bigint NOT NULL,
  53 + "sku_id" bigint NOT NULL,
  54 + "properties" varchar,
  55 + "name" varchar NOT NULL,
  56 + "pic_url" varchar,
  57 + "count" int NOT NULL,
  58 + "original_price" int NOT NULL,
  59 + "original_unit_price" int NOT NULL,
  60 + "discount_price" int NOT NULL,
  61 + "pay_price" int NOT NULL,
  62 + "order_part_price" int NOT NULL,
  63 + "order_divide_price" int NOT NULL,
  64 + "refund_status" int NOT NULL,
  65 + "refund_total" int NOT NULL,
  66 + "creator" varchar DEFAULT '',
  67 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  68 + "updater" varchar DEFAULT '',
  69 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  70 + "deleted" bit NOT NULL DEFAULT FALSE,
  71 + PRIMARY KEY ("id")
  72 +) COMMENT '交易订单明细表';
... ...