mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-11-01 03:28:41 +08:00 
			
		
		
		
	mall + pay:
1. 完善 PayRefundServiceTest 的单元测试
This commit is contained in:
		| @ -212,7 +212,7 @@ public class PayRefundServiceImpl implements PayRefundService { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { | ||||
|     private void notifyRefundSuccess(PayChannelDO channel, PayRefundRespDTO notify) { | ||||
|         // 1.1 查询 PayRefundDO | ||||
|         PayRefundDO refund = refundMapper.selectByAppIdAndNo( | ||||
|                 channel.getAppId(), notify.getOutRefundNo()); | ||||
| @ -246,8 +246,7 @@ public class PayRefundServiceImpl implements PayRefundService { | ||||
|                 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build()); | ||||
|     } | ||||
|  | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { | ||||
|     private void notifyRefundFailure(PayChannelDO channel, PayRefundRespDTO notify) { | ||||
|         // 1.1 查询 PayRefundDO | ||||
|         PayRefundDO refund = refundMapper.selectByAppIdAndNo( | ||||
|                 channel.getAppId(), notify.getOutRefundNo()); | ||||
|  | ||||
| @ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientFactory; | ||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO; | ||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; | ||||
| import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum; | ||||
| import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum; | ||||
| import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; | ||||
| import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO; | ||||
| import cn.iocoder.yudao.module.pay.controller.admin.refund.vo.PayRefundExportReqVO; | ||||
| @ -17,12 +18,14 @@ 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.refund.PayRefundMapper; | ||||
| import cn.iocoder.yudao.module.pay.dal.redis.no.PayNoRedisDAO; | ||||
| import cn.iocoder.yudao.module.pay.enums.notify.PayNotifyTypeEnum; | ||||
| import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | ||||
| import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | ||||
| 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; | ||||
| @ -35,6 +38,7 @@ import java.util.List; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; | ||||
| import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; | ||||
| import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; | ||||
| import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; | ||||
| @ -42,8 +46,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; | ||||
| import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString; | ||||
| import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||||
| import static org.junit.jupiter.api.Assertions.assertNotNull; | ||||
| import static org.junit.jupiter.api.Assertions.*; | ||||
| import static org.mockito.ArgumentMatchers.any; | ||||
| import static org.mockito.ArgumentMatchers.eq; | ||||
| import static org.mockito.Mockito.*; | ||||
| @ -439,4 +442,263 @@ public class PayRefundServiceTest extends BaseDbAndRedisUnitTest { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefund() { | ||||
|         PayRefundServiceImpl payRefundServiceImpl = mock(PayRefundServiceImpl.class); | ||||
|         try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||||
|             springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayRefundServiceImpl.class))) | ||||
|                     .thenReturn(payRefundServiceImpl); | ||||
|  | ||||
|             // 准备参数 | ||||
|             Long channelId = 10L; | ||||
|             PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class); | ||||
|             // mock 方法(channel) | ||||
|             PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||||
|             when(channelService.validPayChannel(eq(10L))).thenReturn(channel); | ||||
|  | ||||
|             // 调用 | ||||
|             refundService.notifyRefund(channelId, refundRespDTO); | ||||
|             // 断言 | ||||
|             verify(payRefundServiceImpl).notifyRefund(same(channel), same(refundRespDTO)); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundSuccess_notFound() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100")); | ||||
|  | ||||
|         // 调用,并断言异常 | ||||
|         assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO), | ||||
|                 REFUND_NOT_FOUND); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundSuccess_isSuccess() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.SUCCESS.getStatus())); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用 | ||||
|         refundService.notifyRefund(channel, refundRespDTO); | ||||
|         // 断言,refund 没有更新,因为已经退款成功 | ||||
|         assertPojoEquals(refund, refundMapper.selectById(refund.getId())); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundSuccess_failure() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.FAILURE.getStatus())); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用,并断言异常 | ||||
|         assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO), | ||||
|                 REFUND_STATUS_IS_NOT_WAITING); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundSuccess_updateOrderException() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.WAITING.getStatus()) | ||||
|                 .setOrderId(100L).setRefundPrice(23)); | ||||
|         refundMapper.insert(refund); | ||||
|         // mock 方法(order + 更新异常) | ||||
|         doThrow(new RuntimeException()).when(orderService) | ||||
|                 .updateOrderRefundPrice(eq(100L), eq(23)); | ||||
|  | ||||
|         // 调用,并断言异常 | ||||
|         assertThrows(RuntimeException.class, () -> refundService.notifyRefund(channel, refundRespDTO)); | ||||
|         // 断言,refund 没有更新,因为事务回滚了 | ||||
|         assertPojoEquals(refund, refundMapper.selectById(refund.getId())); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundSuccess_success() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.WAITING.getStatus()) | ||||
|                 .setOrderId(100L).setRefundPrice(23)); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用 | ||||
|         refundService.notifyRefund(channel, refundRespDTO); | ||||
|         // 断言,refund | ||||
|         refund.setSuccessTime(refundRespDTO.getSuccessTime()) | ||||
|                 .setChannelRefundNo(refundRespDTO.getChannelRefundNo()) | ||||
|                 .setStatus(PayRefundStatusEnum.SUCCESS.getStatus()) | ||||
|                 .setChannelNotifyData(toJsonString(refundRespDTO)); | ||||
|         assertPojoEquals(refund, refundMapper.selectById(refund.getId()), | ||||
|                 "updateTime", "updater"); | ||||
|         // 断言,调用 | ||||
|         verify(orderService).updateOrderRefundPrice(eq(100L), eq(23)); | ||||
|         verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder() | ||||
|                 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build())); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundFailure_notFound() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100")); | ||||
|  | ||||
|         // 调用,并断言异常 | ||||
|         assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO), | ||||
|                 REFUND_NOT_FOUND); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundFailure_isFailure() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 退款失败) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.FAILURE.getStatus())); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用 | ||||
|         refundService.notifyRefund(channel, refundRespDTO); | ||||
|         // 断言,refund 没有更新,因为已经退款失败 | ||||
|         assertPojoEquals(refund, refundMapper.selectById(refund.getId())); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundFailure_isSuccess() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.SUCCESS.getStatus())); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用,并断言异常 | ||||
|         assertServiceException(() -> refundService.notifyRefund(channel, refundRespDTO), | ||||
|                 REFUND_STATUS_IS_NOT_WAITING); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testNotifyRefundFailure_success() { | ||||
|         // 准备参数 | ||||
|         PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L).setAppId(1L)); | ||||
|         PayRefundRespDTO refundRespDTO = randomPojo(PayRefundRespDTO.class, | ||||
|                 o -> o.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus()).setOutRefundNo("R100")); | ||||
|         // mock 数据(refund + 已支付) | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setNo("R100") | ||||
|                 .setStatus(PayRefundStatusEnum.WAITING.getStatus()) | ||||
|                 .setOrderId(100L).setRefundPrice(23)); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用 | ||||
|         refundService.notifyRefund(channel, refundRespDTO); | ||||
|         // 断言,refund | ||||
|         refund.setChannelRefundNo(refundRespDTO.getChannelRefundNo()) | ||||
|                 .setStatus(PayRefundStatusEnum.FAILURE.getStatus()) | ||||
|                 .setChannelNotifyData(toJsonString(refundRespDTO)) | ||||
|                 .setChannelErrorCode(refundRespDTO.getChannelErrorCode()) | ||||
|                 .setChannelErrorMsg(refundRespDTO.getChannelErrorMsg()); | ||||
|         assertPojoEquals(refund, refundMapper.selectById(refund.getId()), | ||||
|                 "updateTime", "updater"); | ||||
|         // 断言,调用 | ||||
|         verify(notifyService).createPayNotifyTask(eq(PayNotifyTaskCreateReqDTO.builder() | ||||
|                 .type(PayNotifyTypeEnum.REFUND.getType()).dataId(refund.getId()).build())); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testSyncRefund_notFound() { | ||||
|         // 准备参数 | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L) | ||||
|                 .setStatus(PayRefundStatusEnum.WAITING.getStatus())); | ||||
|         refundMapper.insert(refund); | ||||
|  | ||||
|         // 调用 | ||||
|         int count = refundService.syncRefund(); | ||||
|         // 断言 | ||||
|         assertEquals(count, 0); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testSyncRefund_waiting() { | ||||
|         assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.WAITING.getStatus()), 0); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testSyncRefund_success() { | ||||
|         assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.SUCCESS.getStatus()), 1); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testSyncRefund_failure() { | ||||
|         assertEquals(testSyncRefund_waitingOrSuccessOrFailure(PayRefundStatusRespEnum.FAILURE.getStatus()), 1); | ||||
|     } | ||||
|  | ||||
|     private int testSyncRefund_waitingOrSuccessOrFailure(Integer status) { | ||||
|         PayRefundServiceImpl payRefundServiceImpl = mock(PayRefundServiceImpl.class); | ||||
|         try (MockedStatic<SpringUtil> springUtilMockedStatic = mockStatic(SpringUtil.class)) { | ||||
|             springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(PayRefundServiceImpl.class))) | ||||
|                     .thenReturn(payRefundServiceImpl); | ||||
|  | ||||
|             // 准备参数 | ||||
|             PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setChannelId(10L) | ||||
|                     .setStatus(PayRefundStatusEnum.WAITING.getStatus()) | ||||
|                     .setOrderNo("P110").setNo("R220")); | ||||
|             refundMapper.insert(refund); | ||||
|             // mock 方法(client) | ||||
|             PayClient client = mock(PayClient.class); | ||||
|             when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); | ||||
|             // mock 方法(client 返回指定状态) | ||||
|             PayRefundRespDTO respDTO = randomPojo(PayRefundRespDTO.class, o -> o.setStatus(status)); | ||||
|             when(client.getRefund(eq("P110"), eq("R220"))).thenReturn(respDTO); | ||||
|             // mock 方法(channel) | ||||
|             PayChannelDO channel = randomPojo(PayChannelDO.class, o -> o.setId(10L)); | ||||
|             when(channelService.validPayChannel(eq(10L))).thenReturn(channel); | ||||
|  | ||||
|             // 调用 | ||||
|             return refundService.syncRefund(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|     public void testSyncRefund_exception() { | ||||
|         // 准备参数 | ||||
|         PayRefundDO refund = randomPojo(PayRefundDO.class, o -> o.setAppId(1L).setChannelId(10L) | ||||
|                 .setStatus(PayRefundStatusEnum.WAITING.getStatus()) | ||||
|                 .setOrderNo("P110").setNo("R220")); | ||||
|         refundMapper.insert(refund); | ||||
|         // mock 方法(client) | ||||
|         PayClient client = mock(PayClient.class); | ||||
|         when(payClientFactory.getPayClient(eq(10L))).thenReturn(client); | ||||
|         // mock 方法(client 抛出异常) | ||||
|         when(client.getRefund(eq("P110"), eq("R220"))).thenThrow(new RuntimeException()); | ||||
|  | ||||
|         // 调用 | ||||
|         int count = refundService.syncRefund(); | ||||
|         // 断言 | ||||
|         assertEquals(count, 0); | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV