Commit 73e1158836c53ab7155ac329939b4f100e42dcf3
1 parent
00e1c30f
by gateway:
1. notify 部分单元测试
Showing
14 changed files
with
238 additions
and
66 deletions
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java
| ... | ... | @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; |
| 7 | 7 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; |
| 8 | 8 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 9 | 9 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 10 | +import com.baomidou.mybatisplus.annotation.TableId; | |
| 10 | 11 | import com.baomidou.mybatisplus.annotation.TableName; |
| 11 | 12 | import lombok.Data; |
| 12 | 13 | import lombok.EqualsAndHashCode; |
| ... | ... | @@ -40,6 +41,7 @@ public class PayNotifyTaskDO extends TenantBaseDO { |
| 40 | 41 | /** |
| 41 | 42 | * 编号,自增 |
| 42 | 43 | */ |
| 44 | + @TableId | |
| 43 | 45 | private Long id; |
| 44 | 46 | /** |
| 45 | 47 | * 应用编号 | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/redis/RedisKeyConstants.java
| ... | ... | @@ -11,7 +11,7 @@ import org.redisson.api.RLock; |
| 11 | 11 | public interface RedisKeyConstants { |
| 12 | 12 | |
| 13 | 13 | RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁", |
| 14 | - "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类 | |
| 14 | + "pay_notify:lock:%d", // 参数来自 DefaultLockKeyBuilder 类 | |
| 15 | 15 | RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构 |
| 16 | 16 | |
| 17 | 17 | /** | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyService.java
| ... | ... | @@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO; |
| 5 | 5 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO; |
| 6 | 6 | import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; |
| 7 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 8 | 7 | |
| 9 | -import javax.validation.Valid; | |
| 10 | 8 | import java.util.List; |
| 11 | 9 | |
| 12 | 10 | /** |
| ... | ... | @@ -19,9 +17,10 @@ public interface PayNotifyService { |
| 19 | 17 | /** |
| 20 | 18 | * 创建回调通知任务 |
| 21 | 19 | * |
| 22 | - * @param reqDTO 任务信息 | |
| 20 | + * @param type 类型 | |
| 21 | + * @param dataId 数据编号 | |
| 23 | 22 | */ |
| 24 | - void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO); | |
| 23 | + void createPayNotifyTask(Integer type, Long dataId); | |
| 25 | 24 | |
| 26 | 25 | /** |
| 27 | 26 | * 执行回调通知 | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.service.notify; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.exceptions.ExceptionUtil; |
| 5 | 5 | import cn.hutool.core.util.ObjectUtil; |
| 6 | +import cn.hutool.extra.spring.SpringUtil; | |
| 6 | 7 | import cn.hutool.http.HttpResponse; |
| 7 | 8 | import cn.hutool.http.HttpUtil; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| ... | ... | @@ -22,7 +23,6 @@ import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper; |
| 22 | 23 | import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; |
| 23 | 24 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; |
| 24 | 25 | import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; |
| 25 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 26 | 26 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 27 | 27 | import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; |
| 28 | 28 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -84,15 +84,10 @@ public class PayNotifyServiceImpl implements PayNotifyService { |
| 84 | 84 | @Resource |
| 85 | 85 | private PayNotifyLockRedisDAO notifyLockCoreRedisDAO; |
| 86 | 86 | |
| 87 | - @Resource | |
| 88 | - @Lazy // 循环依赖(自己依赖自己),避免报错 | |
| 89 | - private PayNotifyServiceImpl self; | |
| 90 | - | |
| 91 | 87 | @Override |
| 92 | 88 | @Transactional(rollbackFor = Exception.class) |
| 93 | - public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) { | |
| 94 | - PayNotifyTaskDO task = new PayNotifyTaskDO(); | |
| 95 | - task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId()); | |
| 89 | + public void createPayNotifyTask(Integer type, Long dataId) { | |
| 90 | + PayNotifyTaskDO task = new PayNotifyTaskDO().setType(type).setDataId(dataId); | |
| 96 | 91 | task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(LocalDateTime.now()) |
| 97 | 92 | .setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1); |
| 98 | 93 | // 补充 appId + notifyUrl 字段 |
| ... | ... | @@ -178,7 +173,7 @@ public class PayNotifyServiceImpl implements PayNotifyService { |
| 178 | 173 | } |
| 179 | 174 | |
| 180 | 175 | // 执行通知 |
| 181 | - self.executeNotify0(dbTask); | |
| 176 | + getSelf().executeNotify0(dbTask); | |
| 182 | 177 | }); |
| 183 | 178 | } |
| 184 | 179 | |
| ... | ... | @@ -285,4 +280,13 @@ public class PayNotifyServiceImpl implements PayNotifyService { |
| 285 | 280 | return notifyLogMapper.selectListByTaskId(taskId); |
| 286 | 281 | } |
| 287 | 282 | |
| 283 | + /** | |
| 284 | + * 获得自身的代理对象,解决 AOP 生效问题 | |
| 285 | + * | |
| 286 | + * @return 自己 | |
| 287 | + */ | |
| 288 | + private PayNotifyServiceImpl getSelf() { | |
| 289 | + return SpringUtil.getBean(getClass()); | |
| 290 | + } | |
| 291 | + | |
| 288 | 292 | } | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/dto/PayNotifyTaskCreateReqDTO.java deleted
| 1 | -package cn.iocoder.yudao.module.pay.service.notify.dto; | |
| 2 | - | |
| 3 | -import lombok.AllArgsConstructor; | |
| 4 | -import lombok.Builder; | |
| 5 | -import lombok.Data; | |
| 6 | -import lombok.NoArgsConstructor; | |
| 7 | - | |
| 8 | -import javax.validation.constraints.NotNull; | |
| 9 | - | |
| 10 | -/** | |
| 11 | - * 支付通知创建 DTO | |
| 12 | - * | |
| 13 | - * @author 芋道源码 | |
| 14 | - */ | |
| 15 | -@Data | |
| 16 | -@Builder | |
| 17 | -@NoArgsConstructor | |
| 18 | -@AllArgsConstructor | |
| 19 | -public class PayNotifyTaskCreateReqDTO { | |
| 20 | - | |
| 21 | - /** | |
| 22 | - * 类型 | |
| 23 | - */ | |
| 24 | - @NotNull(message = "类型不能为空") | |
| 25 | - private Integer type; | |
| 26 | - /** | |
| 27 | - * 数据编号 | |
| 28 | - */ | |
| 29 | - @NotNull(message = "数据编号不能为空") | |
| 30 | - private Long dataId; | |
| 31 | - | |
| 32 | -} |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayNotifyOrderReqVO.java deleted
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/vo/PayRefundOrderReqVO.java deleted
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
| ... | ... | @@ -31,7 +31,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 31 | 31 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 32 | 32 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 33 | 33 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 34 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 35 | 34 | import cn.iocoder.yudao.module.pay.util.MoneyUtils; |
| 36 | 35 | import com.google.common.annotations.VisibleForTesting; |
| 37 | 36 | import lombok.extern.slf4j.Slf4j; |
| ... | ... | @@ -282,8 +281,8 @@ public class PayOrderServiceImpl implements PayOrderService { |
| 282 | 281 | } |
| 283 | 282 | |
| 284 | 283 | // 3. 插入支付通知记录 |
| 285 | - notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | |
| 286 | - .type(PayNotifyTypeEnum.ORDER.getType()).dataId(orderExtension.getOrderId()).build()); | |
| 284 | + notifyService.createPayNotifyTask(PayNotifyTypeEnum.ORDER.getType(), | |
| 285 | + orderExtension.getOrderId()); | |
| 287 | 286 | } |
| 288 | 287 | |
| 289 | 288 | /** | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
| ... | ... | @@ -26,7 +26,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 26 | 26 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 27 | 27 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 28 | 28 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 29 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 30 | 29 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 31 | 30 | import lombok.extern.slf4j.Slf4j; |
| 32 | 31 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -242,8 +241,8 @@ public class PayRefundServiceImpl implements PayRefundService { |
| 242 | 241 | orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice()); |
| 243 | 242 | |
| 244 | 243 | // 3. 插入退款通知记录 |
| 245 | - notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | |
| 246 | - .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); | |
| 244 | + notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(), | |
| 245 | + refund.getId()); | |
| 247 | 246 | } |
| 248 | 247 | |
| 249 | 248 | private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { |
| ... | ... | @@ -273,8 +272,8 @@ public class PayRefundServiceImpl implements PayRefundService { |
| 273 | 272 | log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId()); |
| 274 | 273 | |
| 275 | 274 | // 2. 插入退款通知记录 |
| 276 | - notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder() | |
| 277 | - .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); | |
| 275 | + notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(), | |
| 276 | + refund.getId()); | |
| 278 | 277 | } |
| 279 | 278 | |
| 280 | 279 | @Override | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceTest.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.pay.service.notify; | |
| 2 | + | |
| 3 | +import cn.hutool.extra.spring.SpringUtil; | |
| 4 | +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; | |
| 5 | +import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO; | |
| 6 | +import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; | |
| 7 | +import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO; | |
| 8 | +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper; | |
| 9 | +import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper; | |
| 10 | +import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO; | |
| 11 | +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum; | |
| 12 | +import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | |
| 13 | +import cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration; | |
| 14 | +import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | |
| 15 | +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | |
| 16 | +import cn.iocoder.yudao.module.pay.service.refund.PayRefundServiceImpl; | |
| 17 | +import org.junit.jupiter.api.Test; | |
| 18 | +import org.mockito.MockedStatic; | |
| 19 | +import org.redisson.api.RLock; | |
| 20 | +import org.redisson.api.RedissonClient; | |
| 21 | +import org.springframework.boot.test.mock.mockito.MockBean; | |
| 22 | +import org.springframework.context.annotation.Import; | |
| 23 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 24 | + | |
| 25 | +import javax.annotation.Resource; | |
| 26 | + | |
| 27 | +import java.time.Duration; | |
| 28 | + | |
| 29 | +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime; | |
| 30 | +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | |
| 31 | +import static org.assertj.core.api.Assertions.assertThat; | |
| 32 | +import static org.junit.jupiter.api.Assertions.*; | |
| 33 | +import static org.mockito.ArgumentMatchers.anyString; | |
| 34 | +import static org.mockito.ArgumentMatchers.eq; | |
| 35 | +import static org.mockito.Mockito.*; | |
| 36 | + | |
| 37 | +/** | |
| 38 | + * {@link PayRefundServiceImpl} 的单元测试类 | |
| 39 | + * | |
| 40 | + * @author 芋艿 | |
| 41 | + */ | |
| 42 | +@Import({PayJobConfiguration.class, PayNotifyServiceImpl.class, PayNotifyLockRedisDAO.class}) | |
| 43 | +public class PayNotifyServiceTest extends BaseDbUnitTest { | |
| 44 | + | |
| 45 | + @Resource | |
| 46 | + private PayNotifyServiceImpl notifyService; | |
| 47 | + | |
| 48 | + @MockBean | |
| 49 | + private PayOrderService orderService; | |
| 50 | + @MockBean | |
| 51 | + private PayRefundService refundService; | |
| 52 | + | |
| 53 | + @Resource | |
| 54 | + private PayNotifyTaskMapper notifyTaskMapper; | |
| 55 | + @Resource | |
| 56 | + private PayNotifyLogMapper notifyLogMapper; | |
| 57 | + | |
| 58 | + @MockBean | |
| 59 | + private RedissonClient redissonClient; | |
| 60 | + | |
| 61 | + @Test | |
| 62 | + public void testCreatePayNotifyTask_order() { | |
| 63 | + PayNotifyServiceImpl payNotifyService = mock(PayNotifyServiceImpl.class); | |
| 64 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | |
| 65 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayNotifyServiceImpl.class))) | |
| 66 | + .thenReturn(payNotifyService); | |
| 67 | + | |
| 68 | + // 准备参数 | |
| 69 | + Integer type = PayNotifyTypeEnum.ORDER.getType(); | |
| 70 | + Long dataId = 1L; | |
| 71 | + // mock 方法(order) | |
| 72 | + PayOrderDO order = randomPojo(PayOrderDO.class); | |
| 73 | + when(orderService.getOrder(eq(1L))).thenReturn(order); | |
| 74 | + // mock 方法(lock) | |
| 75 | + mockLock(null); // null 的原因,是咱没办法拿到 taskId 新增 | |
| 76 | + | |
| 77 | + // 调用 | |
| 78 | + notifyService.createPayNotifyTask(type, dataId); | |
| 79 | + // 断言,task | |
| 80 | + PayNotifyTaskDO dbTask = notifyTaskMapper.selectOne(null); | |
| 81 | + assertNotNull(dbTask.getNextNotifyTime()); | |
| 82 | + assertThat(dbTask) | |
| 83 | + .extracting("type", "dataId", "status", "notifyTimes", "maxNotifyTimes", | |
| 84 | + "appId", "merchantOrderId", "notifyUrl") | |
| 85 | + .containsExactly(type, dataId, PayNotifyStatusEnum.WAITING.getStatus(), 0, 9, | |
| 86 | + order.getAppId(), order.getMerchantOrderId(), order.getNotifyUrl()); | |
| 87 | + // 断言,调用 | |
| 88 | + verify(payNotifyService).executeNotify0(eq(dbTask)); | |
| 89 | + } | |
| 90 | + } | |
| 91 | + | |
| 92 | + @Test | |
| 93 | + public void testCreatePayNotifyTask_refund() { | |
| 94 | + PayNotifyServiceImpl payNotifyService = mock(PayNotifyServiceImpl.class); | |
| 95 | + try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | |
| 96 | + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayNotifyServiceImpl.class))) | |
| 97 | + .thenReturn(payNotifyService); | |
| 98 | + | |
| 99 | + // 准备参数 | |
| 100 | + Integer type = PayNotifyTypeEnum.REFUND.getType(); | |
| 101 | + Long dataId = 1L; | |
| 102 | + // mock 方法(refund) | |
| 103 | + PayRefundDO refund = randomPojo(PayRefundDO.class); | |
| 104 | + when(refundService.getRefund(eq(1L))).thenReturn(refund); | |
| 105 | + // mock 方法(lock) | |
| 106 | + mockLock(null); // null 的原因,是咱没办法拿到 taskId 新增 | |
| 107 | + | |
| 108 | + // 调用 | |
| 109 | + notifyService.createPayNotifyTask(type, dataId); | |
| 110 | + // 断言,task | |
| 111 | + PayNotifyTaskDO dbTask = notifyTaskMapper.selectOne(null); | |
| 112 | + assertNotNull(dbTask.getNextNotifyTime()); | |
| 113 | + assertThat(dbTask) | |
| 114 | + .extracting("type", "dataId", "status", "notifyTimes", "maxNotifyTimes", | |
| 115 | + "appId", "merchantOrderId", "notifyUrl") | |
| 116 | + .containsExactly(type, dataId, PayNotifyStatusEnum.WAITING.getStatus(), 0, 9, | |
| 117 | + refund.getAppId(), refund.getMerchantOrderId(), refund.getNotifyUrl()); | |
| 118 | + // 断言,调用 | |
| 119 | + verify(payNotifyService).executeNotify0(eq(dbTask)); | |
| 120 | + } | |
| 121 | + } | |
| 122 | + | |
| 123 | + @Test | |
| 124 | + public void testExecuteNotify() throws InterruptedException { | |
| 125 | + // mock 数据(notify) | |
| 126 | + PayNotifyTaskDO dbTask01 = randomPojo(PayNotifyTaskDO.class, | |
| 127 | + o -> o.setStatus(PayNotifyStatusEnum.WAITING.getStatus()) | |
| 128 | + .setNextNotifyTime(addTime(Duration.ofMinutes(-1)))); | |
| 129 | + notifyTaskMapper.insert(dbTask01); | |
| 130 | + PayNotifyTaskDO dbTask02 = randomPojo(PayNotifyTaskDO.class, | |
| 131 | + o -> o.setStatus(PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus()) | |
| 132 | + .setNextNotifyTime(addTime(Duration.ofMinutes(-1)))); | |
| 133 | + notifyTaskMapper.insert(dbTask02); | |
| 134 | + PayNotifyTaskDO dbTask03 = randomPojo(PayNotifyTaskDO.class, | |
| 135 | + o -> o.setStatus(PayNotifyStatusEnum.REQUEST_FAILURE.getStatus()) | |
| 136 | + .setNextNotifyTime(addTime(Duration.ofMinutes(-1)))); | |
| 137 | + notifyTaskMapper.insert(dbTask03); | |
| 138 | + PayNotifyTaskDO dbTask04 = randomPojo(PayNotifyTaskDO.class, // 不满足状态 | |
| 139 | + o -> o.setStatus(PayNotifyStatusEnum.FAILURE.getStatus()) | |
| 140 | + .setNextNotifyTime(addTime(Duration.ofMinutes(-1)))); | |
| 141 | + notifyTaskMapper.insert(dbTask04); | |
| 142 | + PayNotifyTaskDO dbTask05 = randomPojo(PayNotifyTaskDO.class, // 不满足状态 | |
| 143 | + o -> o.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()) | |
| 144 | + .setNextNotifyTime(addTime(Duration.ofMinutes(-1)))); | |
| 145 | + notifyTaskMapper.insert(dbTask05); | |
| 146 | + PayNotifyTaskDO dbTask06 = randomPojo(PayNotifyTaskDO.class, // 不满足时间 | |
| 147 | + o -> o.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus()) | |
| 148 | + .setNextNotifyTime(addTime(Duration.ofMinutes(1)))); | |
| 149 | + notifyTaskMapper.insert(dbTask06); | |
| 150 | + // mock 方法(lock) | |
| 151 | + mockLock(dbTask01.getId()); | |
| 152 | + mockLock(dbTask02.getId()); | |
| 153 | + mockLock(dbTask03.getId()); | |
| 154 | + | |
| 155 | + // 调用 | |
| 156 | + int count = notifyService.executeNotify(); | |
| 157 | + // 断言,数量 | |
| 158 | + assertEquals(count, 3); | |
| 159 | + } | |
| 160 | + | |
| 161 | + @Test // 由于 HttpUtil 不好 mock,所以只测试异常的情况 | |
| 162 | + public void testExecuteNotify0_exception() { | |
| 163 | + // mock 数据(task) | |
| 164 | + PayNotifyTaskDO task = randomPojo(PayNotifyTaskDO.class, o -> o.setType(-1) | |
| 165 | + .setNotifyTimes(0).setMaxNotifyTimes(9)); | |
| 166 | + notifyTaskMapper.insert(task); | |
| 167 | + | |
| 168 | + // 调用 | |
| 169 | + notifyService.executeNotify0(task); | |
| 170 | + | |
| 171 | + } | |
| 172 | + | |
| 173 | + private void mockLock(Long id) { | |
| 174 | + RLock lock = mock(RLock.class); | |
| 175 | + if (id == null) { | |
| 176 | + when(redissonClient.getLock(anyString())) | |
| 177 | + .thenReturn(lock); | |
| 178 | + } else { | |
| 179 | + when(redissonClient.getLock(eq("pay_notify:lock:" + id))) | |
| 180 | + .thenReturn(lock); | |
| 181 | + } | |
| 182 | + } | |
| 183 | + | |
| 184 | +} | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
| ... | ... | @@ -27,7 +27,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 27 | 27 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 28 | 28 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 29 | 29 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 30 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 31 | 30 | import org.junit.jupiter.api.BeforeEach; |
| 32 | 31 | import org.junit.jupiter.api.Test; |
| 33 | 32 | import org.mockito.MockedStatic; |
| ... | ... | @@ -622,7 +621,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { |
| 622 | 621 | // 断言 PayOrderDO :数据未更新,因为它是 SUCCESS |
| 623 | 622 | assertPojoEquals(order, orderMapper.selectOne(null)); |
| 624 | 623 | // 断言,调用 |
| 625 | - verify(notifyService, never()).createPayNotifyTask(any(PayNotifyTaskCreateReqDTO.class)); | |
| 624 | + verify(notifyService, never()).createPayNotifyTask(anyInt(), anyLong()); | |
| 626 | 625 | } |
| 627 | 626 | |
| 628 | 627 | @Test |
| ... | ... | @@ -661,11 +660,8 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest { |
| 661 | 660 | assertPojoEquals(order, orderMapper.selectOne(null), |
| 662 | 661 | "updateTime", "updater"); |
| 663 | 662 | // 断言,调用 |
| 664 | - verify(notifyService).createPayNotifyTask(argThat(reqDTO -> { | |
| 665 | - assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType()); | |
| 666 | - assertEquals(reqDTO.getDataId(), orderExtension.getOrderId()); | |
| 667 | - return true; | |
| 668 | - })); | |
| 663 | + verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.ORDER.getType()), | |
| 664 | + eq(orderExtension.getOrderId())); | |
| 669 | 665 | } |
| 670 | 666 | |
| 671 | 667 | @Test | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
| ... | ... | @@ -25,7 +25,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; |
| 25 | 25 | import cn.iocoder.yudao.module.pay.service.app.PayAppService; |
| 26 | 26 | import cn.iocoder.yudao.module.pay.service.channel.PayChannelService; |
| 27 | 27 | import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService; |
| 28 | -import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO; | |
| 29 | 28 | import cn.iocoder.yudao.module.pay.service.order.PayOrderService; |
| 30 | 29 | import org.junit.jupiter.api.BeforeEach; |
| 31 | 30 | import org.junit.jupiter.api.Test; |
| ... | ... | @@ -552,8 +551,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { |
| 552 | 551 | "updateTime", "updater"); |
| 553 | 552 | // 断言,调用 |
| 554 | 553 | verify(orderService).updateOrderRefundPrice(eq(100L), eq(23)); |
| 555 | - verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder() | |
| 556 | - .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build())); | |
| 554 | + verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()), | |
| 555 | + eq(refund.getId())); | |
| 557 | 556 | } |
| 558 | 557 | |
| 559 | 558 | @Test |
| ... | ... | @@ -624,8 +623,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { |
| 624 | 623 | assertPojoEquals(refund, refundMapper.selectById(refund.getId()), |
| 625 | 624 | "updateTime", "updater"); |
| 626 | 625 | // 断言,调用 |
| 627 | - verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder() | |
| 628 | - .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build())); | |
| 626 | + verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()), | |
| 627 | + eq(refund.getId())); | |
| 629 | 628 | } |
| 630 | 629 | |
| 631 | 630 | @Test | ... | ... |
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/clean.sql
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -109,3 +109,24 @@ CREATE TABLE IF NOT EXISTS `pay_refund` ( |
| 109 | 109 | `deleted` bit(1) NOT NULL DEFAULT FALSE, |
| 110 | 110 | PRIMARY KEY ("id") |
| 111 | 111 | ) COMMENT = '退款订单'; |
| 112 | + | |
| 113 | +CREATE TABLE IF NOT EXISTS `pay_notify_task` ( | |
| 114 | + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, | |
| 115 | + `app_id` bigint(20) NOT NULL, | |
| 116 | + `type` tinyint(4) NOT NULL, | |
| 117 | + `data_id` bigint(20) NOT NULL, | |
| 118 | + `merchant_order_id` varchar(64) NOT NULL, | |
| 119 | + `status` tinyint(4) NOT NULL, | |
| 120 | + `next_notify_time` datetime(0) NULL DEFAULT NULL, | |
| 121 | + `last_execute_time` datetime(0) NULL DEFAULT NULL, | |
| 122 | + `notify_times` int NOT NULL, | |
| 123 | + `max_notify_times` int NOT NULL, | |
| 124 | + `notify_url` varchar(1024) NOT NULL, | |
| 125 | + `creator` varchar(64) NULL DEFAULT '', | |
| 126 | + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
| 127 | + `updater` varchar(64) NULL DEFAULT '', | |
| 128 | + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
| 129 | + `deleted` bit(1) NOT NULL DEFAULT FALSE, | |
| 130 | + `tenant_id` bigint(20) NOT NULL DEFAULT 0, | |
| 131 | + PRIMARY KEY ("id") | |
| 132 | +) COMMENT = '支付通知'; | ... | ... |