|
@@ -0,0 +1,144 @@
|
|
|
|
|
+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.event.PushEventService;
|
|
|
|
|
+import com.ruoyi.common.utils.LocaleUtils;
|
|
|
|
|
+import com.ruoyi.common.utils.spring.SpringUtils;
|
|
|
|
|
+import com.ruoyi.system.domain.InfoUser;
|
|
|
|
|
+import com.ruoyi.system.domain.RiderPosition;
|
|
|
|
|
+import com.ruoyi.system.service.IInfoUserService;
|
|
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
|
|
+import org.mockito.MockedStatic;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+import org.springframework.context.MessageSource;
|
|
|
|
|
+import org.springframework.context.support.StaticMessageSource;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.List;
|
|
|
|
|
+import java.util.Locale;
|
|
|
|
|
+
|
|
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
|
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
|
|
+import static org.mockito.Mockito.mockStatic;
|
|
|
|
|
+import static org.mockito.Mockito.verify;
|
|
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
|
|
+
|
|
|
|
|
+class NativeRiderBatchPushServiceTest {
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void groupsAndroidRidersByLocalizedTextAndLeavesIosOnExistingPath() {
|
|
|
|
|
+ BusinessPushProperties properties = new BusinessPushProperties();
|
|
|
|
|
+ properties.setMode(BusinessPushProperties.Mode.NATIVE);
|
|
|
|
|
+ IInfoUserService users = mock(IInfoUserService.class);
|
|
|
|
|
+ FcmPushSender fcm = mock(FcmPushSender.class);
|
|
|
|
|
+ PushEventService events = mock(PushEventService.class);
|
|
|
|
|
+ NativeRiderBatchPushService service = new NativeRiderBatchPushService(properties, users, fcm, events);
|
|
|
|
|
+ when(users.getById(1L)).thenReturn(user(1L, "android", "android-1"));
|
|
|
|
|
+ when(users.getById(2L)).thenReturn(user(2L, "android", "android-2"));
|
|
|
|
|
+ when(users.getById(3L)).thenReturn(user(3L, "ios", "ios-3"));
|
|
|
|
|
+ when(users.getById(4L)).thenReturn(user(4L, "android", "android-4"));
|
|
|
|
|
+ when(fcm.sendBatch(RecipientApp.RIDER, List.of("android-1", "android-2"),
|
|
|
|
|
+ "New order", "Nearby order,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}"))
|
|
|
|
|
+ .thenReturn(List.of(new FcmPushSender.DeliveryResult(true, "UNKNOWN"),
|
|
|
|
|
+ new FcmPushSender.DeliveryResult(false, "UNREGISTERED")));
|
|
|
|
|
+ when(fcm.sendBatch(RecipientApp.RIDER, List.of("android-4"),
|
|
|
|
|
+ "新订单", "附近订单,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}"))
|
|
|
|
|
+ .thenReturn(List.of(new FcmPushSender.DeliveryResult(true, "UNKNOWN")));
|
|
|
|
|
+ StaticMessageSource messages = new StaticMessageSource();
|
|
|
|
|
+ messages.addMessage("title.key", Locale.ENGLISH, "New order");
|
|
|
|
|
+ messages.addMessage("content.key", Locale.ENGLISH, "Nearby order");
|
|
|
|
|
+ messages.addMessage("title.key", Locale.CHINESE, "新订单");
|
|
|
|
|
+ messages.addMessage("content.key", Locale.CHINESE, "附近订单");
|
|
|
|
|
+ List<RiderPosition> fallback = new ArrayList<>();
|
|
|
|
|
+ Logger logger = (Logger) LoggerFactory.getLogger(NativeRiderBatchPushService.class);
|
|
|
|
|
+ ListAppender<ILoggingEvent> captured = new ListAppender<>();
|
|
|
|
|
+ captured.start();
|
|
|
|
|
+ logger.addAppender(captured);
|
|
|
|
|
+
|
|
|
|
|
+ try (MockedStatic<LocaleUtils> locales = mockStatic(LocaleUtils.class);
|
|
|
|
|
+ MockedStatic<SpringUtils> beans = mockStatic(SpringUtils.class)) {
|
|
|
|
|
+ locales.when(() -> LocaleUtils.getUserLocale(1L)).thenReturn(Locale.ENGLISH);
|
|
|
|
|
+ locales.when(() -> LocaleUtils.getUserLocale(2L)).thenReturn(Locale.ENGLISH);
|
|
|
|
|
+ locales.when(() -> LocaleUtils.getUserLocale(4L)).thenReturn(Locale.CHINESE);
|
|
|
|
|
+ beans.when(() -> SpringUtils.getBean(MessageSource.class)).thenReturn(messages);
|
|
|
|
|
+
|
|
|
|
|
+ service.sendNewOrder(List.of(rider(1L), rider(2L), rider(3L), rider(4L)),
|
|
|
|
|
+ "title.key", "content.key", "{\"ddId\":\"FOOD-1\"}", "FOOD-1", fallback::add);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ logger.detachAppender(captured);
|
|
|
|
|
+ captured.stop();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ verify(fcm).sendBatch(RecipientApp.RIDER, List.of("android-1", "android-2"),
|
|
|
|
|
+ "New order", "Nearby order,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}");
|
|
|
|
|
+ verify(fcm).sendBatch(RecipientApp.RIDER, List.of("android-4"),
|
|
|
|
|
+ "新订单", "附近订单,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}");
|
|
|
|
|
+ verify(events).PublisherEvent(1L, "New order", "Nearby order,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}");
|
|
|
|
|
+ verify(events).PublisherEvent(2L, "New order", "Nearby order,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}");
|
|
|
|
|
+ verify(events).PublisherEvent(4L, "新订单", "附近订单,NO:FOOD-1", "{\"ddId\":\"FOOD-1\"}");
|
|
|
|
|
+ assertEquals(List.of(3L), fallback.stream().map(RiderPosition::getRiderId).toList());
|
|
|
|
|
+ List<String> logs = captured.list.stream().map(ILoggingEvent::getFormattedMessage).toList();
|
|
|
|
|
+ assertTrue(logs.stream().anyMatch(line -> line.contains("userId=2")
|
|
|
|
|
+ && line.contains("category=UNREGISTERED")));
|
|
|
|
|
+ assertFalse(logs.stream().anyMatch(line -> line.contains("userId=1")
|
|
|
|
|
+ || line.contains("android-1") || line.contains("android-2")));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void multicastTransportFailureIdentifiesEachRiderAndSafeProviderCategory() {
|
|
|
|
|
+ BusinessPushProperties properties = new BusinessPushProperties();
|
|
|
|
|
+ properties.setMode(BusinessPushProperties.Mode.NATIVE);
|
|
|
|
|
+ IInfoUserService users = mock(IInfoUserService.class);
|
|
|
|
|
+ FcmPushSender fcm = mock(FcmPushSender.class);
|
|
|
|
|
+ when(users.getById(1L)).thenReturn(user(1L, "android", "sensitive-1"));
|
|
|
|
|
+ when(users.getById(2L)).thenReturn(user(2L, "android", "sensitive-2"));
|
|
|
|
|
+ when(fcm.sendBatch(RecipientApp.RIDER, List.of("sensitive-1", "sensitive-2"),
|
|
|
|
|
+ "New order", "Nearby order,NO:FOOD-1", "{}"))
|
|
|
|
|
+ .thenThrow(new IllegalStateException("FCM_UNAVAILABLE"));
|
|
|
|
|
+ StaticMessageSource messages = new StaticMessageSource();
|
|
|
|
|
+ messages.addMessage("title.key", Locale.ENGLISH, "New order");
|
|
|
|
|
+ messages.addMessage("content.key", Locale.ENGLISH, "Nearby order");
|
|
|
|
|
+ Logger logger = (Logger) LoggerFactory.getLogger(NativeRiderBatchPushService.class);
|
|
|
|
|
+ ListAppender<ILoggingEvent> captured = new ListAppender<>();
|
|
|
|
|
+ captured.start();
|
|
|
|
|
+ logger.addAppender(captured);
|
|
|
|
|
+ try (MockedStatic<LocaleUtils> locales = mockStatic(LocaleUtils.class);
|
|
|
|
|
+ MockedStatic<SpringUtils> beans = mockStatic(SpringUtils.class)) {
|
|
|
|
|
+ locales.when(() -> LocaleUtils.getUserLocale(1L)).thenReturn(Locale.ENGLISH);
|
|
|
|
|
+ locales.when(() -> LocaleUtils.getUserLocale(2L)).thenReturn(Locale.ENGLISH);
|
|
|
|
|
+ beans.when(() -> SpringUtils.getBean(MessageSource.class)).thenReturn(messages);
|
|
|
|
|
+
|
|
|
|
|
+ new NativeRiderBatchPushService(properties, users, fcm, mock(PushEventService.class))
|
|
|
|
|
+ .sendNewOrder(List.of(rider(1L), rider(2L)), "title.key", "content.key", "{}", "FOOD-1",
|
|
|
|
|
+ ignored -> { });
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ logger.detachAppender(captured);
|
|
|
|
|
+ captured.stop();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<String> logs = captured.list.stream().map(ILoggingEvent::getFormattedMessage).toList();
|
|
|
|
|
+ assertTrue(logs.stream().anyMatch(line -> line.contains("userId=1")
|
|
|
|
|
+ && line.contains("category=FCM_UNAVAILABLE")));
|
|
|
|
|
+ assertTrue(logs.stream().anyMatch(line -> line.contains("userId=2")
|
|
|
|
|
+ && line.contains("category=FCM_UNAVAILABLE")));
|
|
|
|
|
+ assertFalse(logs.stream().anyMatch(line -> line.contains("sensitive-1") || line.contains("sensitive-2")));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static InfoUser user(Long id, String platform, String token) {
|
|
|
|
|
+ InfoUser user = new InfoUser();
|
|
|
|
|
+ user.setUserId(id);
|
|
|
|
|
+ user.setCidType(platform);
|
|
|
|
|
+ user.setDeviceToken(token);
|
|
|
|
|
+ return user;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static RiderPosition rider(Long id) {
|
|
|
|
|
+ RiderPosition rider = new RiderPosition();
|
|
|
|
|
+ rider.setRiderId(id);
|
|
|
|
|
+ return rider;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|