| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- package com.ruoyi.app.push;
- import ch.qos.logback.classic.Logger;
- import ch.qos.logback.classic.spi.ILoggingEvent;
- import ch.qos.logback.core.read.ListAppender;
- import com.ruoyi.app.utils.PayPush;
- import com.ruoyi.app.utils.event.PushEventService;
- import com.ruoyi.common.utils.spring.SpringUtils;
- import com.ruoyi.system.domain.InfoUser;
- import com.ruoyi.system.service.IInfoUserService;
- import org.junit.jupiter.api.Test;
- import org.mockito.MockedStatic;
- import org.slf4j.LoggerFactory;
- import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
- import static org.junit.jupiter.api.Assertions.assertEquals;
- import static org.junit.jupiter.api.Assertions.assertNull;
- import static org.junit.jupiter.api.Assertions.assertTrue;
- import static org.mockito.ArgumentMatchers.any;
- import static org.mockito.ArgumentMatchers.eq;
- import static org.mockito.Mockito.clearInvocations;
- import static org.mockito.Mockito.doThrow;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.mockStatic;
- import static org.mockito.Mockito.never;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- class BusinessPushServiceTest {
- private final BusinessPushProperties properties = new BusinessPushProperties();
- private final IInfoUserService users = mock(IInfoUserService.class);
- private final FcmPushSender fcm = mock(FcmPushSender.class);
- private final ApnsPushSender apns = mock(ApnsPushSender.class);
- private final PayPush uni = mock(PayPush.class);
- @Test
- void defaultModeUsesOnlyExistingUniCloudEndpoints() {
- BusinessPushService service = service();
- service.send(RecipientApp.USER, 1L, "user-cid", "title", "body", "{}");
- service.send(RecipientApp.MERCHANT, 2L, "merchant-cid", "title", "body", "{}");
- service.send(RecipientApp.RIDER, 3L, "rider-cid", "title", "body", "{}");
- verify(uni).apppush("user-cid", "title", "body", "{}");
- verify(uni).shpush("merchant-cid", "title", "body", "{}");
- verify(uni).qspush("rider-cid", "title", "body", "{}");
- verify(users, never()).getById(any());
- verify(fcm, never()).send(any(), any(), any(), any(), any());
- verify(apns, never()).send(any(), any(), any(), any(), any());
- }
- @Test
- void nativeModeRoutesAllSixAppAndPlatformCombinationsUsingLatestToken() {
- properties.setMode(BusinessPushProperties.Mode.NATIVE);
- BusinessPushService service = service();
- long userId = 10L;
- for (RecipientApp app : RecipientApp.values()) {
- for (String platform : new String[]{"android", "ios"}) {
- InfoUser user = user(userId, platform, "native-" + app + "-" + platform);
- when(users.getById(userId)).thenReturn(user);
- service.send(app, userId, null, "title", "body", "{\"ddId\":7}");
- if ("android".equals(platform)) {
- verify(fcm).send(app, user.getDeviceToken(), "title", "body", "{\"ddId\":7}");
- } else {
- verify(apns).send(app, user.getDeviceToken(), "title", "body", "{\"ddId\":7}");
- }
- clearInvocations(fcm, apns);
- userId++;
- }
- }
- verify(uni, never()).apppush(any(), any(), any(), any());
- verify(uni, never()).shpush(any(), any(), any(), any());
- verify(uni, never()).qspush(any(), any(), any(), any());
- }
- @Test
- void nativeAddressUsesLatestAccountAndRejectsMissingOrUnknownPlatform() {
- properties.setMode(BusinessPushProperties.Mode.NATIVE);
- BusinessPushService service = service();
- InfoUser stale = user(9L, "android", "old-token");
- InfoUser latest = user(9L, " IOS ", "new-token");
- when(users.getById(9L)).thenReturn(latest);
- assertEquals("ios:new-token", service.addressKey(stale));
- service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
- verify(apns).send(RecipientApp.USER, "new-token", "title", "body", "{}");
- latest.setCidType("unknown");
- assertNull(service.addressKey(stale));
- service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
- latest.setCidType("android");
- latest.setDeviceToken(" ");
- assertNull(service.addressKey(stale));
- service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}");
- verify(fcm, never()).send(any(), any(), any(), any(), any());
- }
- @Test
- void nativeSenderFailureDoesNotFallBackOrEscapeToBusiness() {
- properties.setMode(BusinessPushProperties.Mode.NATIVE);
- when(users.getById(9L)).thenReturn(user(9L, "android", "native-token"));
- doThrow(new IllegalStateException("FCM_UNREGISTERED"))
- .when(fcm).send(eq(RecipientApp.USER), eq("native-token"), any(), any(), any());
- BusinessPushService service = service();
- assertDoesNotThrow(() -> service.send(RecipientApp.USER, 9L, "uni-cid", "title", "body", "{}"));
- verify(uni, never()).apppush(any(), any(), any(), any());
- }
- @Test
- void nativeLocalFailureLogIdentifiesPlatformAndSafeCategoryWithoutToken() {
- properties.setMode(BusinessPushProperties.Mode.NATIVE);
- when(users.getById(9L)).thenReturn(user(9L, "ios", "secret-device-token"));
- doThrow(new IllegalStateException("APNS_TOKEN_INVALID"))
- .when(apns).send(eq(RecipientApp.USER), eq("secret-device-token"), any(), any(), any());
- Logger logger = (Logger) LoggerFactory.getLogger(BusinessPushService.class);
- ListAppender<ILoggingEvent> captured = new ListAppender<>();
- captured.start();
- logger.addAppender(captured);
- try {
- service().send(RecipientApp.USER, 9L, null, "title", "body", "{}");
- } finally {
- logger.detachAppender(captured);
- captured.stop();
- }
- assertTrue(captured.list.stream().map(ILoggingEvent::getFormattedMessage)
- .anyMatch(message -> message.contains("platform=ios")
- && message.contains("category=APNS_TOKEN_INVALID")
- && !message.contains("secret-device-token")));
- }
- @Test
- void payPushWrapperPublishesOneMessageBeforeRouting() {
- BusinessPushService router = mock(BusinessPushService.class);
- PushEventService events = mock(PushEventService.class);
- try (MockedStatic<SpringUtils> beans = mockStatic(SpringUtils.class)) {
- beans.when(() -> SpringUtils.getBean(BusinessPushService.class)).thenReturn(router);
- PayPush.shPush(new PayPush(), events, 4L, "merchant-cid", "title", "body", "{}", "ios");
- verify(events).PublisherEvent(4L, "title", "body", "{}");
- verify(router).send(RecipientApp.MERCHANT, 4L, "merchant-cid", "title", "body", "{}");
- }
- }
- private BusinessPushService service() {
- return new BusinessPushService(properties, users, fcm, apns, uni);
- }
- private InfoUser user(Long id, String platform, String token) {
- InfoUser user = new InfoUser();
- user.setUserId(id);
- user.setCidType(platform);
- user.setDeviceToken(token);
- return user;
- }
- }
|