feat(wechat): 抽象通知发送器并完善自定义下单相关接口测试
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package com.starry.admin.modules.weichat.service;
|
||||
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||
import javax.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@Profile("!apitest")
|
||||
public class DefaultNotificationSender implements NotificationSender {
|
||||
|
||||
@Resource
|
||||
private WxCustomMpService wxCustomMpService;
|
||||
|
||||
@Override
|
||||
public void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo) {
|
||||
wxCustomMpService.sendOrderMessageAsync(orderInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderFinishMessageAsync(PlayOrderInfoEntity order) {
|
||||
wxCustomMpService.sendOrderFinishMessageAsync(order);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason) {
|
||||
wxCustomMpService.sendOrderCancelMessageAsync(orderInfo, refundReason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo) {
|
||||
wxCustomMpService.sendComplaintMessage(info, orderInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo,
|
||||
String reviewState) {
|
||||
wxCustomMpService.sendCheckMessage(entity, userInfo, reviewState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.starry.admin.modules.weichat.service;
|
||||
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Primary
|
||||
@Component
|
||||
@Profile("apitest")
|
||||
public class MockNotificationSender implements NotificationSender {
|
||||
|
||||
@Override
|
||||
public void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo) {
|
||||
log.debug("[wechat-mock] skip sendOrderMessageAsync orderId={}", orderInfo.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderFinishMessageAsync(PlayOrderInfoEntity order) {
|
||||
log.debug("[wechat-mock] skip sendOrderFinishMessageAsync orderId={}", order.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason) {
|
||||
log.debug("[wechat-mock] skip sendOrderCancelMessageAsync orderId={}", orderInfo.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo) {
|
||||
log.debug("[wechat-mock] skip sendComplaintMessage orderId={}", orderInfo.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo,
|
||||
String reviewState) {
|
||||
log.debug("[wechat-mock] skip sendCheckMessage clerkId={}", userInfo == null ? null : userInfo.getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.starry.admin.modules.weichat.service;
|
||||
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
|
||||
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserReviewInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderComplaintInfoEntity;
|
||||
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||
|
||||
/**
|
||||
* 抽象出发送微信通知的接口,便于在测试环境下替换为 Mock 实现。
|
||||
*/
|
||||
public interface NotificationSender {
|
||||
|
||||
void sendOrderMessageAsync(PlayOrderInfoEntity orderInfo);
|
||||
|
||||
void sendOrderFinishMessageAsync(PlayOrderInfoEntity order);
|
||||
|
||||
void sendOrderCancelMessageAsync(PlayOrderInfoEntity orderInfo, String refundReason);
|
||||
|
||||
void sendComplaintMessage(PlayOrderComplaintInfoEntity info, PlayOrderInfoEntity orderInfo);
|
||||
|
||||
void sendCheckMessage(PlayClerkUserReviewInfoEntity entity, PlayClerkUserInfoEntity userInfo, String reviewState);
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
|
||||
import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
|
||||
import me.chanjar.weixin.mp.config.impl.WxMpMapConfigImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@@ -61,6 +62,7 @@ public class WxCustomMpService {
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor executor;
|
||||
|
||||
|
||||
/**
|
||||
* 支付成功回调地址
|
||||
*/
|
||||
|
||||
@@ -112,6 +112,7 @@ class WxCustomGiftOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(clerkGift).isNotNull();
|
||||
Assertions.assertThat(clerkGift.getGiffNumber()).isEqualTo((long) giftQuantity);
|
||||
|
||||
ensureTenantContext();
|
||||
BigDecimal finalBalance = customUserInfoService.getById(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID)
|
||||
.getAccountBalance();
|
||||
Assertions.assertThat(finalBalance).isEqualByComparingTo(initialBalance.subtract(totalAmount));
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
|
||||
import com.starry.admin.modules.shop.module.constant.CouponUseState;
|
||||
import com.starry.admin.modules.shop.module.entity.PlayCouponDetailsEntity;
|
||||
import com.starry.admin.modules.shop.module.vo.PlayCouponDetailsReturnVo;
|
||||
import com.starry.admin.modules.weichat.service.NotificationSender;
|
||||
import com.starry.admin.modules.weichat.service.WxCustomMpService;
|
||||
import com.starry.admin.modules.withdraw.entity.EarningsLineEntity;
|
||||
import com.starry.admin.modules.withdraw.enums.EarningsType;
|
||||
@@ -38,6 +39,9 @@ import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
|
||||
@MockBean
|
||||
private NotificationSender notificationSender;
|
||||
|
||||
@MockBean
|
||||
private WxCustomMpService wxCustomMpService;
|
||||
|
||||
@@ -158,6 +162,11 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.one();
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
|
||||
PlayCouponDetailsEntity detailBeforeCancel = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailBeforeCancel).isNotNull();
|
||||
Assertions.assertThat(detailBeforeCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailBeforeCancel.getUseTime()).isNotNull();
|
||||
|
||||
String cancelPayload = "{" +
|
||||
"\"orderId\":\"" + order.getId() + "\"," +
|
||||
"\"refundReason\":\"测试取消\"," +
|
||||
@@ -182,6 +191,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("取消订单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
@@ -194,7 +204,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
String remark = "API random force cancel " + IdUtils.getUuid();
|
||||
BigDecimal discount = new BigDecimal("12.00");
|
||||
try {
|
||||
reset(wxCustomMpService);
|
||||
reset(notificationSender);
|
||||
resetCustomerBalance();
|
||||
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
@@ -249,6 +259,12 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayCouponDetailsEntity detailBeforeForceCancel = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailBeforeForceCancel).isNotNull();
|
||||
Assertions.assertThat(detailBeforeForceCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailBeforeForceCancel.getUseTime()).isNotNull();
|
||||
|
||||
ensureTenantContext();
|
||||
orderInfoService.forceCancelOngoingOrder(
|
||||
"2",
|
||||
@@ -267,6 +283,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("强制取消订单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
@@ -280,7 +297,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
String remark = "API random coupon " + IdUtils.getUuid();
|
||||
BigDecimal discount = new BigDecimal("20.00");
|
||||
try {
|
||||
reset(wxCustomMpService);
|
||||
reset(notificationSender);
|
||||
resetCustomerBalance();
|
||||
|
||||
String customerToken = wxTokenService.createWxUserToken(ApiTestDataSeeder.DEFAULT_CUSTOMER_ID);
|
||||
@@ -334,15 +351,13 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
||||
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
||||
|
||||
verify(wxCustomMpService).sendCreateOrderMessageBatch(
|
||||
anyList(),
|
||||
eq(order.getOrderNo()),
|
||||
eq(expectedNet.toString()),
|
||||
eq(order.getCommodityName()),
|
||||
eq(order.getId()));
|
||||
|
||||
String orderId = order.getId();
|
||||
|
||||
PlayCouponDetailsEntity detailAfterOrderPlaced = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailAfterOrderPlaced).isNotNull();
|
||||
Assertions.assertThat(detailAfterOrderPlaced.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailAfterOrderPlaced.getUseTime()).isNotNull();
|
||||
|
||||
mockMvc.perform(get("/wx/clerk/order/accept")
|
||||
.param("id", orderId)
|
||||
.header(USER_HEADER, DEFAULT_USER)
|
||||
@@ -352,7 +367,8 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
verify(wxCustomMpService).sendOrderMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
||||
verify(notificationSender).sendOrderMessageAsync(argThat(o -> o.getId().equals(orderId)));
|
||||
|
||||
|
||||
mockMvc.perform(get("/wx/clerk/order/start")
|
||||
.param("id", orderId)
|
||||
@@ -372,7 +388,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
||||
verify(notificationSender).sendOrderFinishMessageAsync(argThat(o -> orderId.equals(o.getId())));
|
||||
|
||||
ensureTenantContext();
|
||||
PlayOrderInfoEntity completedOrder = playOrderInfoService.selectOrderInfoById(orderId);
|
||||
@@ -397,6 +413,11 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(earningsLine.getAmount()).isEqualByComparingTo(expectedRevenue);
|
||||
|
||||
assertCouponUsed(couponDetailId);
|
||||
|
||||
PlayCouponDetailsEntity detailAfterLifecycle = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailAfterLifecycle).isNotNull();
|
||||
Assertions.assertThat(detailAfterLifecycle.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailAfterLifecycle.getUseTime()).isNotNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
@@ -421,7 +442,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
|
||||
String orderId = placeRandomOrder(remark, customerToken);
|
||||
|
||||
reset(wxCustomMpService);
|
||||
reset(notificationSender);
|
||||
|
||||
ensureTenantContext();
|
||||
mockMvc.perform(get("/wx/clerk/order/accept")
|
||||
@@ -433,9 +454,9 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
verify(wxCustomMpService).sendOrderMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||
verify(notificationSender).sendOrderMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||
|
||||
reset(wxCustomMpService);
|
||||
reset(notificationSender);
|
||||
|
||||
ensureTenantContext();
|
||||
mockMvc.perform(get("/wx/clerk/order/start")
|
||||
@@ -463,7 +484,7 @@ class WxCustomRandomOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.andExpect(jsonPath("$.code").value(200))
|
||||
.andExpect(jsonPath("$.data").value("成功"));
|
||||
|
||||
verify(wxCustomMpService).sendOrderFinishMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||
verify(notificationSender).sendOrderFinishMessageAsync(argThat(order -> order.getId().equals(orderId)));
|
||||
|
||||
ensureTenantContext();
|
||||
long earningsAfter = earningsService.lambdaQuery()
|
||||
|
||||
@@ -86,6 +86,16 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
.one();
|
||||
Assertions.assertThat(order).isNotNull();
|
||||
|
||||
PlayCouponDetailsEntity detailBeforeForceCancel = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailBeforeForceCancel).isNotNull();
|
||||
Assertions.assertThat(detailBeforeForceCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailBeforeForceCancel.getUseTime()).isNotNull();
|
||||
|
||||
PlayCouponDetailsEntity detailBeforeCancel = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailBeforeCancel).isNotNull();
|
||||
Assertions.assertThat(detailBeforeCancel.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailBeforeCancel.getUseTime()).isNotNull();
|
||||
|
||||
String cancelPayload = "{" +
|
||||
"\"orderId\":\"" + order.getId() + "\"," +
|
||||
"\"refundReason\":\"测试取消\"," +
|
||||
@@ -106,9 +116,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||
|
||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detail).isNotNull();
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("取消指定单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
@@ -172,6 +184,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(order.getFinalAmount()).isEqualByComparingTo(expectedNet);
|
||||
Assertions.assertThat(order.getDiscountAmount()).isEqualByComparingTo(discount);
|
||||
|
||||
PlayCouponDetailsEntity detailAfterOrder = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailAfterOrder).isNotNull();
|
||||
Assertions.assertThat(detailAfterOrder.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailAfterOrder.getUseTime()).isNotNull();
|
||||
|
||||
verify(wxCustomMpService).sendCreateOrderMessage(
|
||||
eq(ApiTestDataSeeder.DEFAULT_TENANT_ID),
|
||||
eq(ApiTestDataSeeder.DEFAULT_CLERK_OPEN_ID),
|
||||
@@ -194,6 +211,10 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(order.getEstimatedRevenue()).isEqualByComparingTo(expectedRevenue);
|
||||
|
||||
assertCouponUsed(couponDetailId);
|
||||
PlayCouponDetailsEntity detailAfterComplete = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detailAfterComplete).isNotNull();
|
||||
Assertions.assertThat(detailAfterComplete.getUseState()).isEqualTo(CouponUseState.USED.getCode());
|
||||
Assertions.assertThat(detailAfterComplete.getUseTime()).isNotNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
@@ -273,9 +294,11 @@ class WxCustomSpecifiedOrderApiTest extends WxCustomOrderApiTestSupport {
|
||||
Assertions.assertThat(cancelled.getOrderStatus()).isEqualTo(OrderConstant.OrderStatus.CANCELLED.getCode());
|
||||
|
||||
PlayCouponDetailsEntity detail = couponDetailsService.getById(couponDetailId);
|
||||
Assertions.assertThat(detail).isNotNull();
|
||||
Assertions.assertThat(detail.getUseState())
|
||||
.as("强制取消指定单后优惠券应恢复为未使用")
|
||||
.isEqualTo(CouponUseState.UNUSED.getCode());
|
||||
Assertions.assertThat(detail.getUseTime()).isNull();
|
||||
} finally {
|
||||
CustomSecurityContextHolder.remove();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user