mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 23:31:52 +08:00
by gateway:
1. notify 部分单元测试
This commit is contained in:
parent
00e1c30f57
commit
73e1158836
@ -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.PayNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
||||||
import com.baomidou.mybatisplus.annotation.KeySequence;
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@ -40,6 +41,7 @@ public class PayNotifyTaskDO extends TenantBaseDO {
|
|||||||
/**
|
/**
|
||||||
* 编号,自增
|
* 编号,自增
|
||||||
*/
|
*/
|
||||||
|
@TableId
|
||||||
private Long id;
|
private Long id;
|
||||||
/**
|
/**
|
||||||
* 应用编号
|
* 应用编号
|
||||||
|
@ -11,7 +11,7 @@ import org.redisson.api.RLock;
|
|||||||
public interface RedisKeyConstants {
|
public interface RedisKeyConstants {
|
||||||
|
|
||||||
RedisKeyDefine PAY_NOTIFY_LOCK = new RedisKeyDefine("通知任务的分布式锁",
|
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 数据结构
|
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.controller.admin.notify.vo.PayNotifyTaskPageReqVO;
|
||||||
import cn.iocoder.yudao.module.pay.dal.dataobject.notify.PayNotifyLogDO;
|
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.dal.dataobject.notify.PayNotifyTaskDO;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.List;
|
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.collection.CollUtil;
|
||||||
import cn.hutool.core.exceptions.ExceptionUtil;
|
import cn.hutool.core.exceptions.ExceptionUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.hutool.http.HttpResponse;
|
import cn.hutool.http.HttpResponse;
|
||||||
import cn.hutool.http.HttpUtil;
|
import cn.hutool.http.HttpUtil;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
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.dal.redis.notify.PayNotifyLockRedisDAO;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyStatusEnum;
|
||||||
import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum;
|
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.order.PayOrderService;
|
||||||
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -84,15 +84,10 @@ public class PayNotifyServiceImpl implements PayNotifyService {
|
|||||||
@Resource
|
@Resource
|
||||||
private PayNotifyLockRedisDAO notifyLockCoreRedisDAO;
|
private PayNotifyLockRedisDAO notifyLockCoreRedisDAO;
|
||||||
|
|
||||||
@Resource
|
|
||||||
@Lazy // 循环依赖(自己依赖自己),避免报错
|
|
||||||
private PayNotifyServiceImpl self;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void createPayNotifyTask(PayNotifyTaskCreateReqDTO reqDTO) {
|
public void createPayNotifyTask(Integer type, Long dataId) {
|
||||||
PayNotifyTaskDO task = new PayNotifyTaskDO();
|
PayNotifyTaskDO task = new PayNotifyTaskDO().setType(type).setDataId(dataId);
|
||||||
task.setType(reqDTO.getType()).setDataId(reqDTO.getDataId());
|
|
||||||
task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(LocalDateTime.now())
|
task.setStatus(PayNotifyStatusEnum.WAITING.getStatus()).setNextNotifyTime(LocalDateTime.now())
|
||||||
.setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1);
|
.setNotifyTimes(0).setMaxNotifyTimes(PayNotifyTaskDO.NOTIFY_FREQUENCY.length + 1);
|
||||||
// 补充 appId + notifyUrl 字段
|
// 补充 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);
|
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.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
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.PayNotifyService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
|
||||||
import cn.iocoder.yudao.module.pay.util.MoneyUtils;
|
import cn.iocoder.yudao.module.pay.util.MoneyUtils;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -282,8 +281,8 @@ public class PayOrderServiceImpl implements PayOrderService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 3. 插入支付通知记录
|
// 3. 插入支付通知记录
|
||||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
notifyService.createPayNotifyTask(PayNotifyTypeEnum.ORDER.getType(),
|
||||||
.type(PayNotifyTypeEnum.ORDER.getType()).dataId(orderExtension.getOrderId()).build());
|
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.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
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.PayNotifyService;
|
||||||
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.order.PayOrderService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -242,8 +241,8 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
|
orderService.updateOrderRefundPrice(refund.getOrderId(), refund.getRefundPrice());
|
||||||
|
|
||||||
// 3. 插入退款通知记录
|
// 3. 插入退款通知记录
|
||||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(),
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
|
refund.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
|
private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) {
|
||||||
@ -273,8 +272,8 @@ public class PayRefundServiceImpl implements PayRefundService {
|
|||||||
log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId());
|
log.info("[notifyRefundFailure][退款订单({}) 更新为退款失败]", refund.getId());
|
||||||
|
|
||||||
// 2. 插入退款通知记录
|
// 2. 插入退款通知记录
|
||||||
notifyService.createPayNotifyTask(PayNotifyTaskCreateReqDTO.builder()
|
notifyService.createPayNotifyTask(PayNotifyTypeEnum.REFUND.getType(),
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build());
|
refund.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
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.PayNotifyService;
|
||||||
import cn.iocoder.yudao.module.pay.service.notify.dto.PayNotifyTaskCreateReqDTO;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.MockedStatic;
|
import org.mockito.MockedStatic;
|
||||||
@ -622,7 +621,7 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
|||||||
// 断言 PayOrderDO :数据未更新,因为它是 SUCCESS
|
// 断言 PayOrderDO :数据未更新,因为它是 SUCCESS
|
||||||
assertPojoEquals(order, orderMapper.selectOne(null));
|
assertPojoEquals(order, orderMapper.selectOne(null));
|
||||||
// 断言,调用
|
// 断言,调用
|
||||||
verify(notifyService, never()).createPayNotifyTask(any(PayNotifyTaskCreateReqDTO.class));
|
verify(notifyService, never()).createPayNotifyTask(anyInt(), anyLong());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -661,11 +660,8 @@ public class PayOrderServiceTest extends BaseDbAndRedisUnitTest {
|
|||||||
assertPojoEquals(order, orderMapper.selectOne(null),
|
assertPojoEquals(order, orderMapper.selectOne(null),
|
||||||
"updateTime", "updater");
|
"updateTime", "updater");
|
||||||
// 断言,调用
|
// 断言,调用
|
||||||
verify(notifyService).createPayNotifyTask(argThat(reqDTO -> {
|
verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.ORDER.getType()),
|
||||||
assertEquals(reqDTO.getType(), PayNotifyTypeEnum.ORDER.getType());
|
eq(orderExtension.getOrderId()));
|
||||||
assertEquals(reqDTO.getDataId(), orderExtension.getOrderId());
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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.app.PayAppService;
|
||||||
import cn.iocoder.yudao.module.pay.service.channel.PayChannelService;
|
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.PayNotifyService;
|
||||||
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.order.PayOrderService;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -552,8 +551,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
|||||||
"updateTime", "updater");
|
"updateTime", "updater");
|
||||||
// 断言,调用
|
// 断言,调用
|
||||||
verify(orderService).updateOrderRefundPrice(eq(100L), eq(23));
|
verify(orderService).updateOrderRefundPrice(eq(100L), eq(23));
|
||||||
verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
|
verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()),
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
|
eq(refund.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -624,8 +623,8 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest {
|
|||||||
assertPojoEquals(refund, refundMapper.selectById(refund.getId()),
|
assertPojoEquals(refund, refundMapper.selectById(refund.getId()),
|
||||||
"updateTime", "updater");
|
"updateTime", "updater");
|
||||||
// 断言,调用
|
// 断言,调用
|
||||||
verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder()
|
verify(notifyService).createPayNotifyTask(eq(PayNotifyTypeEnum.REFUND.getType()),
|
||||||
.type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()));
|
eq(refund.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -3,3 +3,4 @@ DELETE FROM pay_channel;
|
|||||||
DELETE FROM pay_order;
|
DELETE FROM pay_order;
|
||||||
DELETE FROM pay_order_extension;
|
DELETE FROM pay_order_extension;
|
||||||
DELETE FROM pay_refund;
|
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,
|
`deleted` bit(1) NOT NULL DEFAULT FALSE,
|
||||||
PRIMARY KEY ("id")
|
PRIMARY KEY ("id")
|
||||||
) COMMENT = '退款订单';
|
) 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 = '支付通知';
|
||||||
|
Loading…
Reference in New Issue
Block a user