2026-06-26 20b96473f2520590a0dca6b775b81e3ea06a77a0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
package cn.iocoder.yudao.module.trade.service.order;
 
import cn.hutool.core.util.IdUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.module.member.api.address.MemberAddressApi;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.pay.api.order.PayOrderApi;
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.promotion.api.coupon.CouponApi;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
import cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express.DeliveryExpressCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderItemMapper;
import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
import cn.iocoder.yudao.module.trade.dal.redis.no.TradeNoRedisDAO;
import cn.iocoder.yudao.module.trade.enums.delivery.DeliveryTypeEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderConfig;
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
import cn.iocoder.yudao.module.trade.service.cart.CartServiceImpl;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressServiceImpl;
import cn.iocoder.yudao.module.trade.service.message.TradeMessageServiceImpl;
import cn.iocoder.yudao.module.trade.service.order.handler.TradeOrderHandler;
import cn.iocoder.yudao.module.trade.service.price.TradePriceServiceImpl;
import cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculator;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
 
import java.time.Duration;
 
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
 
/**
 * {@link TradeOrderUpdateServiceImpl} 的单元测试类
 *
 * @author LeeYan9
 * @since 2022-09-07
 */
@Disabled // TODO 芋艿:后续 fix 补充的单测
@Import({TradeOrderUpdateServiceImpl.class, TradeOrderConfig.class, CartServiceImpl.class, TradePriceServiceImpl.class,
        DeliveryExpressServiceImpl.class, TradeMessageServiceImpl.class
})
public class TradeOrderUpdateServiceTest extends BaseDbUnitTest {
 
    @Resource
    private TradeOrderUpdateServiceImpl tradeOrderUpdateService;
 
    @Resource
    private TradeOrderMapper tradeOrderMapper;
    @Resource
    private TradeOrderItemMapper tradeOrderItemMapper;
 
    @MockitoBean
    private MemberUserApi memberUserApi;
    @MockitoBean
    private ProductSpuApi productSpuApi;
    @MockitoBean
    private ProductSkuApi productSkuApi;
    @MockitoBean
    private ProductCommentApi productCommentApi;
    //    @MockitoBean
//    private PriceApi priceApi;
    @MockitoBean
    private PayOrderApi payOrderApi;
    @MockitoBean
    private MemberAddressApi addressApi;
    @MockitoBean
    private CouponApi couponApi;
 
    @MockitoBean
    private TradeOrderProperties tradeOrderProperties;
    @MockitoBean
    private TradeNoRedisDAO tradeNoRedisDAO;
    @MockitoBean
    private TradeOrderHandler tradeOrderHandler;
    @MockitoBean
    private TradePriceCalculator tradePriceCalculator;
    @MockitoBean
    private NotifyMessageSendApi notifyMessageSendApi;
    @MockitoBean
    private DeliveryExpressService deliveryExpressService;
 
    @BeforeEach
    public void setUp() {
        when(tradeOrderProperties.getPayAppKey()).thenReturn("mall");
        when(tradeOrderProperties.getPayExpireTime()).thenReturn(Duration.ofDays(1));
        when(tradeNoRedisDAO.generate(anyString())).thenReturn(IdUtil.randomUUID());
    }
 
//    @Test
//    public void testCreateTradeOrder_success() {
//        // 准备参数
//        Long userId = 100L;
//        String userIp = "127.0.0.1";
////        AppTradeOrderCreateReqVO reqVO = new AppTradeOrderCreateReqVO()
////                .setAddressId(10L).setCouponId(101L).setRemark("我是备注").setFromCart(true)
////                .setItems(Arrays.asList(new AppTradeOrderCreateReqVO.Item().setSkuId(1L).setCount(3),
////                        new AppTradeOrderCreateReqVO.Item().setSkuId(2L).setCount(4)));
//        AppTradeOrderCreateReqVO reqVO = null;
//        // TODO 芋艿:重新高下
//        // mock 方法(商品 SKU 检查)
//        ProductSkuRespDTO sku01 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(1L).setSpuId(11L)
//                .setPrice(50).setStock(100)
//                .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(111L).setValueId(222L))));
//        ProductSkuRespDTO sku02 = randomPojo(ProductSkuRespDTO.class, o -> o.setId(2L).setSpuId(21L)
//                .setPrice(20).setStock(50))
//                .setProperties(singletonList(new ProductPropertyValueDetailRespDTO().setPropertyId(333L).setValueId(444L)));
//        when(productSkuApi.getSkuList(eq(asSet(1L, 2L)))).thenReturn(Arrays.asList(sku01, sku02));
//        // mock 方法(商品 SPU 检查)
//        ProductSpuRespDTO spu01 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(11L)
//                .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()).setName("商品 1"));
//        ProductSpuRespDTO spu02 = randomPojo(ProductSpuRespDTO.class, o -> o.setId(21L)
//                .setStatus(ProductSpuStatusEnum.ENABLE.getStatus()));
//        when(productSpuApi.getSpuList(eq(asSet(11L, 21L)))).thenReturn(Arrays.asList(spu01, spu02));
//        // mock 方法(用户收件地址的校验)
//        MemberAddressRespDTO addressRespDTO = new MemberAddressRespDTO().setId(10L).setUserId(userId).setName("芋艿")
//                .setMobile("15601691300").setAreaId(3306).setDetailAddress("土豆村");
//        when(addressApi.getAddress(eq(10L), eq(userId))).thenReturn(addressRespDTO);
//        // mock 方法(价格计算)
//        PriceCalculateRespDTO.OrderItem priceOrderItem01 = new PriceCalculateRespDTO.OrderItem()
//                .setSpuId(11L).setSkuId(1L).setCount(3).setOriginalPrice(150).setOriginalUnitPrice(50)
//                .setDiscountPrice(20).setPayPrice(130).setOrderPartPrice(7).setOrderDividePrice(35);
//        PriceCalculateRespDTO.OrderItem priceOrderItem02 = new PriceCalculateRespDTO.OrderItem()
//                .setSpuId(21L).setSkuId(2L).setCount(4).setOriginalPrice(80).setOriginalUnitPrice(20)
//                .setDiscountPrice(40).setPayPrice(40).setOrderPartPrice(15).setOrderDividePrice(25);
//        PriceCalculateRespDTO.Order priceOrder = new PriceCalculateRespDTO.Order()
//                .setTotalPrice(230).setDiscountPrice(0).setCouponPrice(30)
//                .setPointPrice(10).setDeliveryPrice(20).setPayPrice(80).setCouponId(101L).setCouponPrice(30)
//                .setItems(Arrays.asList(priceOrderItem01, priceOrderItem02));
//        when(priceApi.calculatePrice(argThat(priceCalculateReqDTO -> {
//            assertEquals(priceCalculateReqDTO.getUserId(), 100L);
//            assertEquals(priceCalculateReqDTO.getCouponId(), 101L);
//            assertEquals(priceCalculateReqDTO.getItems().get(0).getSkuId(), 1L);
//            assertEquals(priceCalculateReqDTO.getItems().get(0).getCount(), 3);
//            assertEquals(priceCalculateReqDTO.getItems().get(1).getSkuId(), 2L);
//            assertEquals(priceCalculateReqDTO.getItems().get(1).getCount(), 4);
//            return true;
//        }))).thenReturn(new PriceCalculateRespDTO().setOrder(priceOrder));
//        // mock 方法(创建支付单)
//        when(payOrderApi.createOrder(argThat(createReqDTO -> {
//            assertEquals(createReqDTO.getAppId(), 888L);
//            assertEquals(createReqDTO.getUserIp(), userIp);
//            assertNotNull(createReqDTO.getMerchantOrderId()); // 由于 tradeOrderId 后生成,只能校验非空
//            assertEquals(createReqDTO.getSubject(), "商品 1 等多件");
//            assertNull(createReqDTO.getBody());
//            assertEquals(createReqDTO.getPrice(), 80);
//            assertNotNull(createReqDTO.getExpireTime());
//            return true;
//        }))).thenReturn(1000L);
//
//        // 调用方法
//        TradeOrderDO order = tradeOrderUpdateService.createOrder(userId, userIp, reqVO, null);
//        // 断言 TradeOrderDO 订单
//        List<TradeOrderDO> tradeOrderDOs = tradeOrderMapper.selectList();
//        assertEquals(tradeOrderDOs.size(), 1);
//        TradeOrderDO tradeOrderDO = tradeOrderDOs.get(0);
//        assertEquals(tradeOrderDO.getId(), order.getId());
//        assertNotNull(tradeOrderDO.getNo());
//        assertEquals(tradeOrderDO.getType(), TradeOrderTypeEnum.NORMAL.getType());
//        assertEquals(tradeOrderDO.getTerminal(), TerminalEnum.H5.getTerminal());
//        assertEquals(tradeOrderDO.getUserId(), userId);
//        assertEquals(tradeOrderDO.getUserIp(), userIp);
//        assertEquals(tradeOrderDO.getStatus(), TradeOrderStatusEnum.UNPAID.getStatus());
//        assertEquals(tradeOrderDO.getProductCount(), 7);
//        assertNull(tradeOrderDO.getFinishTime());
//        assertNull(tradeOrderDO.getCancelTime());
//        assertNull(tradeOrderDO.getCancelType());
//        assertEquals(tradeOrderDO.getUserRemark(), "我是备注");
//        assertNull(tradeOrderDO.getRemark());
//        assertFalse(tradeOrderDO.getPayStatus());
//        assertNull(tradeOrderDO.getPayTime());
//        assertEquals(tradeOrderDO.getTotalPrice(), 230);
//        assertEquals(tradeOrderDO.getDiscountPrice(), 0);
//        assertEquals(tradeOrderDO.getAdjustPrice(), 0);
//        assertEquals(tradeOrderDO.getPayPrice(), 80);
//        assertEquals(tradeOrderDO.getPayOrderId(), 1000L);
//        assertNull(tradeOrderDO.getPayChannelCode());
//        assertNull(tradeOrderDO.getLogisticsId());
//        assertNull(tradeOrderDO.getDeliveryTime());
//        assertNull(tradeOrderDO.getReceiveTime());
//        assertEquals(tradeOrderDO.getReceiverName(), "芋艿");
//        assertEquals(tradeOrderDO.getReceiverMobile(), "15601691300");
//        assertEquals(tradeOrderDO.getReceiverAreaId(), 3306);
//        assertEquals(tradeOrderDO.getReceiverDetailAddress(), "土豆村");
//        assertEquals(tradeOrderDO.getRefundStatus(), TradeOrderRefundStatusEnum.NONE.getStatus());
//        assertEquals(tradeOrderDO.getRefundPrice(), 0);
//        assertEquals(tradeOrderDO.getCouponPrice(), 30);
//        assertEquals(tradeOrderDO.getPointPrice(), 10);
//        // 断言 TradeOrderItemDO 订单(第 1 个)
//        List<TradeOrderItemDO> tradeOrderItemDOs = tradeOrderItemMapper.selectList();
//        assertEquals(tradeOrderItemDOs.size(), 2);
//        TradeOrderItemDO tradeOrderItemDO01 = tradeOrderItemDOs.get(0);
//        assertNotNull(tradeOrderItemDO01.getId());
//        assertEquals(tradeOrderItemDO01.getUserId(), userId);
//        assertEquals(tradeOrderItemDO01.getOrderId(), order.getId());
//        assertEquals(tradeOrderItemDO01.getSpuId(), 11L);
//        assertEquals(tradeOrderItemDO01.getSkuId(), 1L);
//        assertEquals(tradeOrderItemDO01.getProperties().size(), 1);
//        assertEquals(tradeOrderItemDO01.getProperties().get(0).getPropertyId(), 111L);
//        assertEquals(tradeOrderItemDO01.getProperties().get(0).getValueId(), 222L);
//        //assertEquals(tradeOrderItemDO01.getSpuName(), sku01.getSpuName()); TODO 找不到spuName
//        assertEquals(tradeOrderItemDO01.getPicUrl(), sku01.getPicUrl());
//        assertEquals(tradeOrderItemDO01.getCount(), 3);
////        assertEquals(tradeOrderItemDO01.getOriginalPrice(), 150);
//        assertEquals(tradeOrderItemDO01.getPrice(), 50);
//        assertEquals(tradeOrderItemDO01.getDiscountPrice(), 20);
//        assertEquals(tradeOrderItemDO01.getPayPrice(), 130);
//        assertEquals(tradeOrderItemDO01.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
//        // 断言 TradeOrderItemDO 订单(第 2 个)
//        TradeOrderItemDO tradeOrderItemDO02 = tradeOrderItemDOs.get(1);
//        assertNotNull(tradeOrderItemDO02.getId());
//        assertEquals(tradeOrderItemDO02.getUserId(), userId);
//        assertEquals(tradeOrderItemDO02.getOrderId(), order.getId());
//        assertEquals(tradeOrderItemDO02.getSpuId(), 21L);
//        assertEquals(tradeOrderItemDO02.getSkuId(), 2L);
//        assertEquals(tradeOrderItemDO02.getProperties().size(), 1);
//        assertEquals(tradeOrderItemDO02.getProperties().get(0).getPropertyId(), 333L);
//        assertEquals(tradeOrderItemDO02.getProperties().get(0).getValueId(), 444L);
//        //assertEquals(tradeOrderItemDO02.getSpuName(), sku02.getSpuName()); TODO 找不到spuName
//        assertEquals(tradeOrderItemDO02.getPicUrl(), sku02.getPicUrl());
//        assertEquals(tradeOrderItemDO02.getCount(), 4);
////        assertEquals(tradeOrderItemDO02.getOriginalPrice(), 80);
//        assertEquals(tradeOrderItemDO02.getPrice(), 20);
//        assertEquals(tradeOrderItemDO02.getDiscountPrice(), 40);
//        assertEquals(tradeOrderItemDO02.getPayPrice(), 40);
//        assertEquals(tradeOrderItemDO02.getAfterSaleStatus(), TradeOrderItemAfterSaleStatusEnum.NONE.getStatus());
//        // 校验调用
//        verify(productSkuApi).updateSkuStock(argThat(updateStockReqDTO -> {
//            assertEquals(updateStockReqDTO.getItems().size(), 2);
//            assertEquals(updateStockReqDTO.getItems().get(0).getId(), 1L);
//            assertEquals(updateStockReqDTO.getItems().get(0).getIncrCount(), 3);
//            assertEquals(updateStockReqDTO.getItems().get(1).getId(), 2L);
//            assertEquals(updateStockReqDTO.getItems().get(1).getIncrCount(), 4);
//            return true;
//        }));
//        verify(couponApi).useCoupon(argThat(reqDTO -> {
//            assertEquals(reqDTO.getId(), reqVO.getCouponId());
//            assertEquals(reqDTO.getUserId(), userId);
//            assertEquals(reqDTO.getOrderId(), order.getId());
//            return true;
//        }));
//    }
 
    @Test
    public void testUpdateOrderPaid() {
        // mock 数据(TradeOrder)
        TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
            o.setId(1L).setStatus(TradeOrderStatusEnum.UNPAID.getStatus());
            o.setPayOrderId(10L).setPayStatus(false).setPayPrice(100).setPayTime(null);
        });
        tradeOrderMapper.insert(order);
        // 准备参数
        Long id = 1L;
        Long payOrderId = 10L;
        // mock 方法(支付单)
        when(payOrderApi.getOrder(eq(10L))).thenReturn(randomPojo(PayOrderRespDTO.class,
                o -> o.setStatus(PayOrderStatusEnum.SUCCESS.getStatus()).setChannelCode("wx_pub")
                        .setMerchantOrderId("1")).setPrice(100));
 
        // 调用
        tradeOrderUpdateService.updateOrderPaid(id, payOrderId);
        // 断言
        TradeOrderDO dbOrder = tradeOrderMapper.selectById(id);
        assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
        assertTrue(dbOrder.getPayStatus());
        assertNotNull(dbOrder.getPayTime());
        assertEquals(dbOrder.getPayChannelCode(), "wx_pub");
    }
 
    @Test
    public void testDeliveryOrder() {
        // mock 数据(TradeOrder)
        TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
            o.setId(1L).setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus());
            o.setLogisticsId(null).setLogisticsNo(null).setDeliveryTime(null);
            o.setRefundStatus(TradeOrderRefundStatusEnum.NONE.getStatus());
            o.setDeliveryType(DeliveryTypeEnum.EXPRESS.getType());
        });
        tradeOrderMapper.insert(order);
 
        DeliveryExpressCreateReqVO expressCreateReqVO = new DeliveryExpressCreateReqVO();
        expressCreateReqVO.setCode("code").setName("Name").setLogo("logo").setSort(0).setStatus(CommonStatusEnum.ENABLE.getStatus());
        Long deliveryExpressId = deliveryExpressService.createDeliveryExpress(expressCreateReqVO);
        // 准备参数
        TradeOrderDeliveryReqVO deliveryReqVO = new TradeOrderDeliveryReqVO().setId(1L)
                .setLogisticsId(deliveryExpressId).setLogisticsNo("100");
 
        // mock 方法(支付单)
 
        // 调用
        tradeOrderUpdateService.deliveryOrder(deliveryReqVO);
        // 断言
        TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L);
        assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.DELIVERED.getStatus());
        assertPojoEquals(dbOrder, deliveryReqVO);
        assertNotNull(dbOrder.getDeliveryTime());
    }
 
    @Test
    public void testReceiveOrder() {
        // mock 数据(TradeOrder)
        TradeOrderDO order = randomPojo(TradeOrderDO.class, o -> {
            o.setId(1L).setUserId(10L).setStatus(TradeOrderStatusEnum.DELIVERED.getStatus());
            o.setReceiveTime(null);
        });
        tradeOrderMapper.insert(order);
        // 准备参数
        Long id = 1L;
        Long userId = 10L;
        // mock 方法(支付单)
 
        // 调用
        tradeOrderUpdateService.receiveOrderByMember(userId, id);
        // 断言
        TradeOrderDO dbOrder = tradeOrderMapper.selectById(1L);
        assertEquals(dbOrder.getStatus(), TradeOrderStatusEnum.COMPLETED.getStatus());
        assertNotNull(dbOrder.getReceiveTime());
    }
 
}