mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-04 12:18:42 +08:00 
			
		
		
		
	by gateway:
1. notify 部分单元测试
This commit is contained in:
		@@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.KeySequence;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableId;
 | 
			
		||||
import com.baomidou.mybatisplus.annotation.TableName;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.EqualsAndHashCode;
 | 
			
		||||
@@ -40,6 +41,7 @@ public class PayNotifyTaskDO extends TenantBaseDO {
 | 
			
		||||
    /**
 | 
			
		||||
     * 编号,自增
 | 
			
		||||
     */
 | 
			
		||||
    @TableId
 | 
			
		||||
    private Long id;
 | 
			
		||||
    /**
 | 
			
		||||
     * 应用编号
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import org.redisson.api.RLock;
 | 
			
		||||
public interface RedisKeyConstants {
 | 
			
		||||
 | 
			
		||||
    RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁",
 | 
			
		||||
            "pay_notify:lock:", // 参数来自 DefaultLockKeyBuilder 类
 | 
			
		||||
            "pay_notify:lock:%d", // 参数来自 DefaultLockKeyBuilder 类
 | 
			
		||||
            RedisKeyDefine.KeyTypeEnum.HASH, RLock.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); // Redisson 的 Lock 锁,使用 Hash 数据结构
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -4,9 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
 | 
			
		||||
import javax.validation.Valid;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -19,9 +17,10 @@ public interface PayNotifyService {
 | 
			
		||||
    /**
 | 
			
		||||
     * 创建回调通知任务
 | 
			
		||||
     *
 | 
			
		||||
     * @param reqDTO 任务信息
 | 
			
		||||
     * @param type 类型
 | 
			
		||||
     * @param dataId 数据编号
 | 
			
		||||
     */
 | 
			
		||||
    void createPayNotifyTask(@Valid PayNotifyTaskCreateReqDTO reqDTO);
 | 
			
		||||
    void createPayNotifyTask(Integer type, Long dataId);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 执行回调通知
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.service.notify;
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import cn.hutool.core.exceptions.ExceptionUtil;
 | 
			
		||||
import cn.hutool.core.util.ObjectUtil;
 | 
			
		||||
import cn.hutool.extra.spring.SpringUtil;
 | 
			
		||||
import cn.hutool.http.HttpResponse;
 | 
			
		||||
import cn.hutool.http.HttpUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 | 
			
		||||
@@ -22,7 +23,6 @@ import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@@ -84,15 +84,10 @@ public class PayNotifyServiceImpl implements PayNotifyService {
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyLockRedisDAO notifyLockCoreRedisDAO;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    @Lazy // 循环依赖(自己依赖自己),避免报错
 | 
			
		||||
    private PayNotifyServiceImpl self;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    @Transactional(rollbackFor = Exception.class)
 | 
			
		||||
    public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) {
 | 
			
		||||
        PayNotifyTaskDO task = new PayNotifyTaskDO();
 | 
			
		||||
        task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId());
 | 
			
		||||
    public void createPayNotifyTask(Integer type, Long dataId) {
 | 
			
		||||
        PayNotifyTaskDO task = new PayNotifyTaskDO().setType(type).setDataId(dataId);
 | 
			
		||||
        task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(LocalDateTime.now())
 | 
			
		||||
                .setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1);
 | 
			
		||||
        // 补充 appId + notifyUrl 字段
 | 
			
		||||
@@ -178,7 +173,7 @@ public class PayNotifyServiceImpl implements PayNotifyService {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // 执行通知
 | 
			
		||||
            self.executeNotify0(dbTask);
 | 
			
		||||
            getSelf().executeNotify0(dbTask);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -285,4 +280,13 @@ public class PayNotifyServiceImpl implements PayNotifyService {
 | 
			
		||||
        return notifyLogMapper.selectListByTaskId(taskId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 获得自身的代理对象,解决 AOP 生效问题
 | 
			
		||||
     *
 | 
			
		||||
     * @return 自己
 | 
			
		||||
     */
 | 
			
		||||
    private PayNotifyServiceImpl getSelf() {
 | 
			
		||||
        return SpringUtil.getBean(getClass());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,32 +0,0 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.service.notify.dto;
 | 
			
		||||
 | 
			
		||||
import lombok.AllArgsConstructor;
 | 
			
		||||
import lombok.Builder;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
import lombok.NoArgsConstructor;
 | 
			
		||||
 | 
			
		||||
import javax.validation.constraints.NotNull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 支付通知创建 DTO
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋道源码
 | 
			
		||||
 */
 | 
			
		||||
@Data
 | 
			
		||||
@Builder
 | 
			
		||||
@NoArgsConstructor
 | 
			
		||||
@AllArgsConstructor
 | 
			
		||||
public class PayNotifyTaskCreateReqDTO {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 类型
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "类型不能为空")
 | 
			
		||||
    private Integer type;
 | 
			
		||||
    /**
 | 
			
		||||
     * 数据编号
 | 
			
		||||
     */
 | 
			
		||||
    @NotNull(message = "数据编号不能为空")
 | 
			
		||||
    private Long dataId;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -31,7 +31,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.util.MoneyUtils;
 | 
			
		||||
import com.google.common.annotations.VisibleForTesting;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
@@ -282,8 +281,8 @@ public class PayOrderServiceImpl implements PayOrderService {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 3. 插入支付通知记录
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.ORDER.getType()).dataId(orderExtension.getOrderId()).build());
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTypeEnum.ORDER.getType(),
 | 
			
		||||
                orderExtension.getOrderId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 | 
			
		||||
import lombok.extern.slf4j.Slf4j;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
@@ -242,8 +241,8 @@ public class PayRefundServiceImpl implements PayRefundService {
 | 
			
		||||
        orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
 | 
			
		||||
 | 
			
		||||
        // 3. 插入退款通知记录
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(),
 | 
			
		||||
                refund.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
 | 
			
		||||
@@ -273,8 +272,8 @@ public class PayRefundServiceImpl implements PayRefundService {
 | 
			
		||||
        log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId());
 | 
			
		||||
 | 
			
		||||
        // 2. 插入退款通知记录
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
 | 
			
		||||
        notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(),
 | 
			
		||||
                refund.getId());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,184 @@
 | 
			
		||||
package cn.iocoder.yudao.module.pay.service.notify;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.extra.spring.SpringUtil;
 | 
			
		||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyTaskDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyLogMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.mysql.notify.PayNotifyTaskMapper;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.dal.redis.notify.PayNotifyLockRedisDAO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.framework.job.config.PayJobConfiguration;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundServiceImpl;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.mockito.MockedStatic;
 | 
			
		||||
import org.redisson.api.RLock;
 | 
			
		||||
import org.redisson.api.RedissonClient;
 | 
			
		||||
import org.springframework.boot.test.mock.mockito.MockBean;
 | 
			
		||||
import org.springframework.context.annotation.Import;
 | 
			
		||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 | 
			
		||||
 | 
			
		||||
import javax.annotation.Resource;
 | 
			
		||||
 | 
			
		||||
import java.time.Duration;
 | 
			
		||||
 | 
			
		||||
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
 | 
			
		||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
 | 
			
		||||
import static org.assertj.core.api.Assertions.assertThat;
 | 
			
		||||
import static org.junit.jupiter.api.Assertions.*;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.anyString;
 | 
			
		||||
import static org.mockito.ArgumentMatchers.eq;
 | 
			
		||||
import static org.mockito.Mockito.*;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link PayRefundServiceImpl} 的单元测试类
 | 
			
		||||
 *
 | 
			
		||||
 * @author 芋艿
 | 
			
		||||
 */
 | 
			
		||||
@Import({PayJobConfiguration.class, PayNotifyServiceImpl.class, PayNotifyLockRedisDAO.class})
 | 
			
		||||
public class PayNotifyServiceTest extends BaseDbUnitTest {
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyServiceImpl notifyService;
 | 
			
		||||
 | 
			
		||||
    @MockBean
 | 
			
		||||
    private PayOrderService orderService;
 | 
			
		||||
    @MockBean
 | 
			
		||||
    private PayRefundService refundService;
 | 
			
		||||
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyTaskMapper notifyTaskMapper;
 | 
			
		||||
    @Resource
 | 
			
		||||
    private PayNotifyLogMapper notifyLogMapper;
 | 
			
		||||
 | 
			
		||||
    @MockBean
 | 
			
		||||
    private RedissonClient redissonClient;
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreatePayNotifyTask_order() {
 | 
			
		||||
        PayNotifyServiceImpl payNotifyService = mock(PayNotifyServiceImpl.class);
 | 
			
		||||
        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
 | 
			
		||||
            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayNotifyServiceImpl.class)))
 | 
			
		||||
                    .thenReturn(payNotifyService);
 | 
			
		||||
 | 
			
		||||
            // 准备参数
 | 
			
		||||
            Integer type = PayNotifyTypeEnum.ORDER.getType();
 | 
			
		||||
            Long dataId = 1L;
 | 
			
		||||
            // mock 方法(order)
 | 
			
		||||
            PayOrderDO order = randomPojo(PayOrderDO.class);
 | 
			
		||||
            when(orderService.getOrder(eq(1L))).thenReturn(order);
 | 
			
		||||
            // mock 方法(lock)
 | 
			
		||||
            mockLock(null); // null 的原因,是咱没办法拿到 taskId 新增
 | 
			
		||||
 | 
			
		||||
            // 调用
 | 
			
		||||
            notifyService.createPayNotifyTask(type, dataId);
 | 
			
		||||
            // 断言,task
 | 
			
		||||
            PayNotifyTaskDO dbTask = notifyTaskMapper.selectOne(null);
 | 
			
		||||
            assertNotNull(dbTask.getNextNotifyTime());
 | 
			
		||||
            assertThat(dbTask)
 | 
			
		||||
                    .extracting("type", "dataId", "status", "notifyTimes", "maxNotifyTimes",
 | 
			
		||||
                            "appId", "merchantOrderId", "notifyUrl")
 | 
			
		||||
                    .containsExactly(type, dataId, PayNotifyStatusEnum.WAITING.getStatus(), 0, 9,
 | 
			
		||||
                            order.getAppId(), order.getMerchantOrderId(), order.getNotifyUrl());
 | 
			
		||||
            // 断言,调用
 | 
			
		||||
            verify(payNotifyService).executeNotify0(eq(dbTask));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testCreatePayNotifyTask_refund() {
 | 
			
		||||
        PayNotifyServiceImpl payNotifyService = mock(PayNotifyServiceImpl.class);
 | 
			
		||||
        try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) {
 | 
			
		||||
            springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayNotifyServiceImpl.class)))
 | 
			
		||||
                    .thenReturn(payNotifyService);
 | 
			
		||||
 | 
			
		||||
            // 准备参数
 | 
			
		||||
            Integer type = PayNotifyTypeEnum.REFUND.getType();
 | 
			
		||||
            Long dataId = 1L;
 | 
			
		||||
            // mock 方法(refund)
 | 
			
		||||
            PayRefundDO refund = randomPojo(PayRefundDO.class);
 | 
			
		||||
            when(refundService.getRefund(eq(1L))).thenReturn(refund);
 | 
			
		||||
            // mock 方法(lock)
 | 
			
		||||
            mockLock(null); // null 的原因,是咱没办法拿到 taskId 新增
 | 
			
		||||
 | 
			
		||||
            // 调用
 | 
			
		||||
            notifyService.createPayNotifyTask(type, dataId);
 | 
			
		||||
            // 断言,task
 | 
			
		||||
            PayNotifyTaskDO dbTask = notifyTaskMapper.selectOne(null);
 | 
			
		||||
            assertNotNull(dbTask.getNextNotifyTime());
 | 
			
		||||
            assertThat(dbTask)
 | 
			
		||||
                    .extracting("type", "dataId", "status", "notifyTimes", "maxNotifyTimes",
 | 
			
		||||
                            "appId", "merchantOrderId", "notifyUrl")
 | 
			
		||||
                    .containsExactly(type, dataId, PayNotifyStatusEnum.WAITING.getStatus(), 0, 9,
 | 
			
		||||
                            refund.getAppId(), refund.getMerchantOrderId(), refund.getNotifyUrl());
 | 
			
		||||
            // 断言,调用
 | 
			
		||||
            verify(payNotifyService).executeNotify0(eq(dbTask));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testExecuteNotify() throws InterruptedException {
 | 
			
		||||
        // mock 数据(notify)
 | 
			
		||||
        PayNotifyTaskDO dbTask01 = randomPojo(PayNotifyTaskDO.class,
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.WAITING.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(-1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask01);
 | 
			
		||||
        PayNotifyTaskDO dbTask02 = randomPojo(PayNotifyTaskDO.class,
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.REQUEST_SUCCESS.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(-1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask02);
 | 
			
		||||
        PayNotifyTaskDO dbTask03 = randomPojo(PayNotifyTaskDO.class,
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.REQUEST_FAILURE.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(-1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask03);
 | 
			
		||||
        PayNotifyTaskDO dbTask04 = randomPojo(PayNotifyTaskDO.class, // 不满足状态
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.FAILURE.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(-1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask04);
 | 
			
		||||
        PayNotifyTaskDO dbTask05 = randomPojo(PayNotifyTaskDO.class, // 不满足状态
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(-1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask05);
 | 
			
		||||
        PayNotifyTaskDO dbTask06 = randomPojo(PayNotifyTaskDO.class, // 不满足时间
 | 
			
		||||
                o -> o.setStatus(PayNotifyStatusEnum.SUCCESS.getStatus())
 | 
			
		||||
                        .setNextNotifyTime(addTime(Duration.ofMinutes(1))));
 | 
			
		||||
        notifyTaskMapper.insert(dbTask06);
 | 
			
		||||
        // mock 方法(lock)
 | 
			
		||||
        mockLock(dbTask01.getId());
 | 
			
		||||
        mockLock(dbTask02.getId());
 | 
			
		||||
        mockLock(dbTask03.getId());
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        int count = notifyService.executeNotify();
 | 
			
		||||
        // 断言,数量
 | 
			
		||||
        assertEquals(count, 3);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test // 由于 HttpUtil 不好 mock,所以只测试异常的情况
 | 
			
		||||
    public void testExecuteNotify0_exception() {
 | 
			
		||||
        // mock 数据(task)
 | 
			
		||||
        PayNotifyTaskDO task = randomPojo(PayNotifyTaskDO.class, o -> o.setType(-1)
 | 
			
		||||
                .setNotifyTimes(0).setMaxNotifyTimes(9));
 | 
			
		||||
        notifyTaskMapper.insert(task);
 | 
			
		||||
 | 
			
		||||
        // 调用
 | 
			
		||||
        notifyService.executeNotify0(task);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void mockLock(Long id) {
 | 
			
		||||
        RLock lock = mock(RLock.class);
 | 
			
		||||
        if (id == null) {
 | 
			
		||||
            when(redissonClient.getLock(anyString()))
 | 
			
		||||
                    .thenReturn(lock);
 | 
			
		||||
        } else {
 | 
			
		||||
            when(redissonClient.getLock(eq("pay_notify:lock:" + id)))
 | 
			
		||||
                    .thenReturn(lock);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -27,7 +27,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import org.junit.jupiter.api.BeforeEach;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
import org.mockito.MockedStatic;
 | 
			
		||||
@@ -622,7 +621,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
 | 
			
		||||
        // 断言 PayOrderDO :数据未更新,因为它是 SUCCESS
 | 
			
		||||
        assertPojoEquals(order, orderMapper.selectOne(null));
 | 
			
		||||
        // 断言,调用
 | 
			
		||||
        verify(notifyService, never()).createPayNotifyTask(any(PayNotifyTaskCreateReqDTO.class));
 | 
			
		||||
        verify(notifyService, never()).createPayNotifyTask(anyInt(), anyLong());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -661,11 +660,8 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
 | 
			
		||||
        assertPojoEquals(order, orderMapper.selectOne(null),
 | 
			
		||||
                "updateTime", "updater");
 | 
			
		||||
        // 断言,调用
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(argThat(reqDTO -> {
 | 
			
		||||
            assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType());
 | 
			
		||||
            assertEquals(reqDTO.getDataId(), orderExtension.getOrderId());
 | 
			
		||||
            return true;
 | 
			
		||||
        }));
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.ORDER.getType()),
 | 
			
		||||
            eq(orderExtension.getOrderId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,6 @@ import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.PayNotifyService;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
 | 
			
		||||
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
 | 
			
		||||
import org.junit.jupiter.api.BeforeEach;
 | 
			
		||||
import org.junit.jupiter.api.Test;
 | 
			
		||||
@@ -552,8 +551,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
 | 
			
		||||
                "updateTime", "updater");
 | 
			
		||||
        // 断言,调用
 | 
			
		||||
        verify(orderService).updateOrderRefundPrice(eq(100L), eq(23));
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()),
 | 
			
		||||
                eq(refund.getId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
@@ -624,8 +623,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
 | 
			
		||||
        assertPojoEquals(refund, refundMapper.selectById(refund.getId()),
 | 
			
		||||
                "updateTime", "updater");
 | 
			
		||||
        // 断言,调用
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
 | 
			
		||||
                .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
 | 
			
		||||
        verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()),
 | 
			
		||||
                eq(refund.getId()));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Test
 | 
			
		||||
 
 | 
			
		||||
@@ -3,3 +3,4 @@ DELETE FROM pay_channel;
 | 
			
		||||
DELETE FROM pay_order;
 | 
			
		||||
DELETE FROM pay_order_extension;
 | 
			
		||||
DELETE FROM pay_refund;
 | 
			
		||||
DELETE FROM pay_notify_task;
 | 
			
		||||
@@ -109,3 +109,24 @@ CREATE TABLE IF NOT EXISTS `pay_refund` (
 | 
			
		||||
    `deleted`            bit(1)        NOT NULL DEFAULT FALSE,
 | 
			
		||||
    PRIMARY KEY ("id")
 | 
			
		||||
) COMMENT = '退款订单';
 | 
			
		||||
 | 
			
		||||
CREATE TABLE IF NOT EXISTS `pay_notify_task` (
 | 
			
		||||
    "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
 | 
			
		||||
    `app_id`             bigint(20)    NOT NULL,
 | 
			
		||||
    `type`               tinyint(4)    NOT NULL,
 | 
			
		||||
    `data_id`           bigint(20)    NOT NULL,
 | 
			
		||||
    `merchant_order_id`           varchar(64)    NOT NULL,
 | 
			
		||||
    `status`             tinyint(4)    NOT NULL,
 | 
			
		||||
    `next_notify_time`       datetime(0)   NULL     DEFAULT NULL,
 | 
			
		||||
    `last_execute_time`       datetime(0)   NULL     DEFAULT NULL,
 | 
			
		||||
    `notify_times`         int    NOT NULL,
 | 
			
		||||
    `max_notify_times`         int    NOT NULL,
 | 
			
		||||
    `notify_url`         varchar(1024) NOT NULL,
 | 
			
		||||
    `creator`            varchar(64)   NULL     DEFAULT '',
 | 
			
		||||
    `create_time`        datetime(0)   NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
    `updater`            varchar(64)   NULL     DEFAULT '',
 | 
			
		||||
    `update_time`        datetime(0)   NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 | 
			
		||||
    `deleted`            bit(1)        NOT NULL DEFAULT FALSE,
 | 
			
		||||
    `tenant_id`           bigint(20)    NOT NULL DEFAULT 0,
 | 
			
		||||
    PRIMARY KEY ("id")
 | 
			
		||||
) COMMENT = '支付通知';
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user