BusinessPushServiceTest.java 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package com.ruoyi.app.push;
  2. import ch.qos.logback.classic.Logger;
  3. import ch.qos.logback.classic.spi.ILoggingEvent;
  4. import ch.qos.logback.core.read.ListAppender;
  5. import com.ruoyi.app.utils.PayPush;
  6. import com.ruoyi.app.utils.event.PushEventService;
  7. import com.ruoyi.common.utils.spring.SpringUtils;
  8. import com.ruoyi.system.domain.InfoUser;
  9. import com.ruoyi.system.service.IInfoUserService;
  10. import org.junit.jupiter.api.Test;
  11. import org.mockito.MockedStatic;
  12. import org.slf4j.LoggerFactory;
  13. import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
  14. import static org.junit.jupiter.api.Assertions.assertEquals;
  15. import static org.junit.jupiter.api.Assertions.assertNull;
  16. import static org.junit.jupiter.api.Assertions.assertTrue;
  17. import static org.mockito.ArgumentMatchers.any;
  18. import static org.mockito.ArgumentMatchers.eq;
  19. import static org.mockito.Mockito.clearInvocations;
  20. import static org.mockito.Mockito.doThrow;
  21. import static org.mockito.Mockito.mock;
  22. import static org.mockito.Mockito.mockStatic;
  23. import static org.mockito.Mockito.never;
  24. import static org.mockito.Mockito.verify;
  25. import static org.mockito.Mockito.when;
  26. class BusinessPushServiceTest {
  27. private final BusinessPushProperties properties = new BusinessPushProperties();
  28. private final IInfoUserService users = mock(IInfoUserService.class);
  29. private final FcmPushSender fcm = mock(FcmPushSender.class);
  30. private final ApnsPushSender apns = mock(ApnsPushSender.class);
  31. private final PayPush uni = mock(PayPush.class);
  32. @Test
  33. void defaultModeUsesOnlyExistingUniCloudEndpoints() {
  34. BusinessPushService service = service();
  35. service.send(RecipientApp.USER, 1L, "user-cid", "title", "body", "{}");
  36. service.send(RecipientApp.MERCHANT, 2L, "merchant-cid", "title", "body", "{}");
  37. service.send(RecipientApp.RIDER, 3L, "rider-cid", "title", "body", "{}");
  38. verify(uni).apppush("user-cid", "title", "body", "{}");
  39. verify(uni).shpush("merchant-cid", "title", "body", "{}");
  40. verify(uni).qspush("rider-cid", "title", "body", "{}");
  41. verify(users, never()).getById(any());
  42. verify(fcm, never()).send(any(), any(), any(), any(), any());
  43. verify(apns, never()).send(any(), any(), any(), any(), any());
  44. }
  45. @Test
  46. void nativeModeRoutesAllSixAppAndPlatformCombinationsUsingLatestToken() {
  47. properties.setMode(BusinessPushProperties.Mode.NATIVE);
  48. BusinessPushService service = service();
  49. long userId = 10L;
  50. for (RecipientApp app : RecipientApp.values()) {
  51. for (String platform : new String[]{"android", "ios"}) {
  52. InfoUser user = user(userId, platform, "native-" + app + "-" + platform);
  53. when(users.getById(userId)).thenReturn(user);
  54. service.send(app, userId, null, "title", "body", "{\"ddId\":7}");
  55. if ("android".equals(platform)) {
  56. verify(fcm).send(app, user.getDeviceToken(), "title", "body", "{\"ddId\":7}");
  57. } else {
  58. verify(apns).send(app, user.getDeviceToken(), "title", "body", "{\"ddId\":7}");
  59. }
  60. clearInvocations(fcm, apns);
  61. userId++;
  62. }
  63. }
  64. verify(uni, never()).apppush(any(), any(), any(), any());
  65. verify(uni, never()).shpush(any(), any(), any(), any());
  66. verify(uni, never()).qspush(any(), any(), any(), any());
  67. }
  68. @Test
  69. void nativeAddressUsesLatestAccountAndRejectsMissingOrUnknownPlatform() {
  70. properties.setMode(BusinessPushProperties.Mode.NATIVE);
  71. BusinessPushService service = service();
  72. InfoUser stale = user(9L, "android", "old-token");
  73. InfoUser latest = user(9L, " IOS ", "new-token");
  74. when(users.getById(9L)).thenReturn(latest);
  75. assertEquals("ios:new-token", service.addressKey(stale));
  76. service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
  77. verify(apns).send(RecipientApp.USER, "new-token", "title", "body", "{}");
  78. latest.setCidType("unknown");
  79. assertNull(service.addressKey(stale));
  80. service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
  81. latest.setCidType("android");
  82. latest.setDeviceToken(" ");
  83. assertNull(service.addressKey(stale));
  84. service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
  85. verify(fcm, never()).send(any(), any(), any(), any(), any());
  86. }
  87. @Test
  88. void nativeSenderFailureDoesNotFallBackOrEscapeToBusiness() {
  89. properties.setMode(BusinessPushProperties.Mode.NATIVE);
  90. when(users.getById(9L)).thenReturn(user(9L, "android", "native-token"));
  91. doThrow(new IllegalStateException("FCM_UNREGISTERED"))
  92. .when(fcm).send(eq(RecipientApp.USER), eq("native-token"), any(), any(), any());
  93. BusinessPushService service = service();
  94. assertDoesNotThrow(() -> service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}"));
  95. verify(uni, never()).apppush(any(), any(), any(), any());
  96. }
  97. @Test
  98. void nativeLocalFailureLogIdentifiesPlatformAndSafeCategoryWithoutToken() {
  99. properties.setMode(BusinessPushProperties.Mode.NATIVE);
  100. when(users.getById(9L)).thenReturn(user(9L, "ios", "secret-device-token"));
  101. doThrow(new IllegalStateException("APNS_TOKEN_INVALID"))
  102. .when(apns).send(eq(RecipientApp.USER), eq("secret-device-token"), any(), any(), any());
  103. Logger logger = (Logger) LoggerFactory.getLogger(BusinessPushService.class);
  104. ListAppender<ILoggingEvent> captured = new ListAppender<>();
  105. captured.start();
  106. logger.addAppender(captured);
  107. try {
  108. service().send(RecipientApp.USER, 9L, null, "title", "body", "{}");
  109. } finally {
  110. logger.detachAppender(captured);
  111. captured.stop();
  112. }
  113. assertTrue(captured.list.stream().map(ILoggingEvent::getFormattedMessage)
  114. .anyMatch(message -> message.contains("platform=ios")
  115. && message.contains("category=APNS_TOKEN_INVALID")
  116. && !message.contains("secret-device-token")));
  117. }
  118. @Test
  119. void payPushWrapperPublishesOneMessageBeforeRouting() {
  120. BusinessPushService router = mock(BusinessPushService.class);
  121. PushEventService events = mock(PushEventService.class);
  122. try (MockedStatic<SpringUtils> beans = mockStatic(SpringUtils.class)) {
  123. beans.when(() -> SpringUtils.getBean(BusinessPushService.class)).thenReturn(router);
  124. PayPush.shPush(new PayPush(), events, 4L, "merchant-cid", "title", "body", "{}", "ios");
  125. verify(events).PublisherEvent(4L, "title", "body", "{}");
  126. verify(router).send(RecipientApp.MERCHANT, 4L, "merchant-cid", "title", "body", "{}");
  127. }
  128. }
  129. private BusinessPushService service() {
  130. return new BusinessPushService(properties, users, fcm, apns, uni);
  131. }
  132. private InfoUser user(Long id, String platform, String token) {
  133. InfoUser user = new InfoUser();
  134. user.setUserId(id);
  135. user.setCidType(platform);
  136. user.setDeviceToken(token);
  137. return user;
  138. }
  139. }