|
|
@@ -0,0 +1,178 @@
|
|
|
+package com.tzld.piaoquan.longarticle.service.local;
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.alibaba.fastjson.serializer.SerializerFeature;
|
|
|
+import com.tzld.piaoquan.longarticle.component.AdNewRedisClient;
|
|
|
+import com.tzld.piaoquan.longarticle.dao.mapper.growth.GrowthRootSourceChannelMapper;
|
|
|
+import com.tzld.piaoquan.longarticle.dao.mapper.longarticle.LongArticleRootSourceChannelMapper;
|
|
|
+import com.tzld.piaoquan.longarticle.model.dto.RootSourceChannelCache;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.mockito.ArgumentCaptor;
|
|
|
+
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertThrows;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import static org.mockito.ArgumentMatchers.any;
|
|
|
+import static org.mockito.ArgumentMatchers.anyInt;
|
|
|
+import static org.mockito.ArgumentMatchers.anyLong;
|
|
|
+import static org.mockito.ArgumentMatchers.anyString;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.verify;
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
+
|
|
|
+class RootSourceChannelSyncServiceTest {
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void syncReadsAllFourBusinessLines() {
|
|
|
+ LongArticleRootSourceChannelMapper longArticleMapper = mock(LongArticleRootSourceChannelMapper.class);
|
|
|
+ GrowthRootSourceChannelMapper growthMapper = mock(GrowthRootSourceChannelMapper.class);
|
|
|
+ AdNewRedisClient redisClient = mock(AdNewRedisClient.class);
|
|
|
+ when(longArticleMapper.selectRootSourceChannels(anyString(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectCgiReplyChannels(anyLong(), any(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectQwPlanChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectGzhPushChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+
|
|
|
+ RootSourceChannelSyncService.SyncResult result =
|
|
|
+ newService(longArticleMapper, growthMapper, redisClient).sync();
|
|
|
+
|
|
|
+ assertEquals(0, result.getTotalCount());
|
|
|
+ verify(longArticleMapper).selectRootSourceChannels(anyString(), anyLong(), anyInt());
|
|
|
+ verify(growthMapper).selectCgiReplyChannels(anyLong(), any(), anyInt());
|
|
|
+ verify(growthMapper).selectQwPlanChannels(anyLong(), anyLong(), anyInt());
|
|
|
+ verify(growthMapper).selectGzhPushChannels(anyLong(), anyLong(), anyInt());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void sourceFailureFailsTheWholeJob() {
|
|
|
+ LongArticleRootSourceChannelMapper longArticleMapper = mock(LongArticleRootSourceChannelMapper.class);
|
|
|
+ GrowthRootSourceChannelMapper growthMapper = mock(GrowthRootSourceChannelMapper.class);
|
|
|
+ AdNewRedisClient redisClient = mock(AdNewRedisClient.class);
|
|
|
+ when(longArticleMapper.selectRootSourceChannels(anyString(), anyLong(), anyInt()))
|
|
|
+ .thenThrow(new IllegalStateException("database unavailable"));
|
|
|
+
|
|
|
+ RootSourceChannelSyncService service = newService(longArticleMapper, growthMapper, redisClient);
|
|
|
+
|
|
|
+ assertThrows(IllegalStateException.class, service::sync);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void todaySyncReadsAllFourBusinessLines() {
|
|
|
+ LongArticleRootSourceChannelMapper longArticleMapper = mock(LongArticleRootSourceChannelMapper.class);
|
|
|
+ GrowthRootSourceChannelMapper growthMapper = mock(GrowthRootSourceChannelMapper.class);
|
|
|
+ AdNewRedisClient redisClient = mock(AdNewRedisClient.class);
|
|
|
+ when(longArticleMapper.selectRootSourceChannels(anyString(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectCgiReplyChannels(anyLong(), any(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectQwPlanChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectGzhPushChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+
|
|
|
+ RootSourceChannelSyncService.SyncResult result =
|
|
|
+ newService(longArticleMapper, growthMapper, redisClient).syncToday();
|
|
|
+
|
|
|
+ assertEquals(0, result.getTotalCount());
|
|
|
+ verify(longArticleMapper).selectRootSourceChannels(anyString(), anyLong(), anyInt());
|
|
|
+ verify(growthMapper).selectCgiReplyChannels(anyLong(), any(), anyInt());
|
|
|
+ verify(growthMapper).selectQwPlanChannels(anyLong(), anyLong(), anyInt());
|
|
|
+ verify(growthMapper).selectGzhPushChannels(anyLong(), anyLong(), anyInt());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ void longArticleIsEnrichedAndSerializedWithCommonFieldsOnly() {
|
|
|
+ LongArticleRootSourceChannelMapper longArticleMapper = mock(LongArticleRootSourceChannelMapper.class);
|
|
|
+ GrowthRootSourceChannelMapper growthMapper = mock(GrowthRootSourceChannelMapper.class);
|
|
|
+ AdNewRedisClient redisClient = mock(AdNewRedisClient.class);
|
|
|
+
|
|
|
+ RootSourceChannelCache channel = new RootSourceChannelCache();
|
|
|
+ channel.setRootSourceId("longArticles_test");
|
|
|
+ channel.setAccountId("gh_test");
|
|
|
+ channel.setAccountName("旧名称");
|
|
|
+ channel.setSourceTimestamp(TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()));
|
|
|
+ RootSourceChannelCache account = new RootSourceChannelCache();
|
|
|
+ account.setAccountId("gh_test");
|
|
|
+ account.setAccountName("公众号名称");
|
|
|
+ account.setChannel("partner_channel");
|
|
|
+
|
|
|
+ when(longArticleMapper.selectRootSourceChannels(anyString(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.singletonList(channel));
|
|
|
+ when(growthMapper.selectAccountsByGhIds(any())).thenReturn(Collections.singletonList(account));
|
|
|
+ when(growthMapper.selectCgiReplyChannels(anyLong(), any(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectQwPlanChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectGzhPushChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(redisClient.writeChannels(any())).thenReturn(1);
|
|
|
+
|
|
|
+ newService(longArticleMapper, growthMapper, redisClient).sync();
|
|
|
+
|
|
|
+ ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
|
|
|
+ verify(redisClient).writeChannels(captor.capture());
|
|
|
+ RootSourceChannelCache enriched = (RootSourceChannelCache) captor.getValue().get(0);
|
|
|
+ String json = JSONObject.toJSONString(enriched, SerializerFeature.WriteMapNullValue);
|
|
|
+ JSONObject value = JSONObject.parseObject(json);
|
|
|
+ assertEquals("partner_channel", value.getString("channel"));
|
|
|
+ assertEquals("公众号名称", value.getString("accountName"));
|
|
|
+ assertTrue(value.containsKey("rootSourceId"));
|
|
|
+ assertFalse(value.containsKey("accountId"));
|
|
|
+ assertFalse(value.containsKey("sourceTimestamp"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void gzhPushChannelsUseCommonRedisFields() {
|
|
|
+ LongArticleRootSourceChannelMapper longArticleMapper = mock(LongArticleRootSourceChannelMapper.class);
|
|
|
+ GrowthRootSourceChannelMapper growthMapper = mock(GrowthRootSourceChannelMapper.class);
|
|
|
+ AdNewRedisClient redisClient = mock(AdNewRedisClient.class);
|
|
|
+ RootSourceChannelCache channel = new RootSourceChannelCache();
|
|
|
+ channel.setSourceId(101L);
|
|
|
+ channel.setSourceTimestamp(System.currentTimeMillis());
|
|
|
+ channel.setRootSourceId("gzh_push_test");
|
|
|
+ channel.setChannel("partner_channel");
|
|
|
+ channel.setAccountName("公众号名称");
|
|
|
+
|
|
|
+ when(longArticleMapper.selectRootSourceChannels(anyString(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectCgiReplyChannels(anyLong(), any(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectQwPlanChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.emptyList());
|
|
|
+ when(growthMapper.selectGzhPushChannels(anyLong(), anyLong(), anyInt()))
|
|
|
+ .thenReturn(Collections.singletonList(channel), Collections.emptyList());
|
|
|
+ when(redisClient.writeChannels(any())).thenReturn(1);
|
|
|
+
|
|
|
+ RootSourceChannelSyncService.SyncResult result =
|
|
|
+ newService(longArticleMapper, growthMapper, redisClient).sync();
|
|
|
+
|
|
|
+ assertEquals(1, result.getGzhPushCount());
|
|
|
+ assertEquals(1, result.getTotalCount());
|
|
|
+ ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
|
|
|
+ verify(redisClient).writeChannels(captor.capture());
|
|
|
+ RootSourceChannelCache cached = (RootSourceChannelCache) captor.getValue().get(0);
|
|
|
+ JSONObject value = JSONObject.parseObject(JSONObject.toJSONString(cached, SerializerFeature.WriteMapNullValue));
|
|
|
+ assertEquals("partner_channel", value.getString("channel"));
|
|
|
+ assertEquals("公众号名称", value.getString("accountName"));
|
|
|
+ assertFalse(value.containsKey("sourceId"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private RootSourceChannelSyncService newService(LongArticleRootSourceChannelMapper longArticleMapper,
|
|
|
+ GrowthRootSourceChannelMapper growthMapper,
|
|
|
+ AdNewRedisClient redisClient) {
|
|
|
+ RootSourceChannelSyncService service = new RootSourceChannelSyncService();
|
|
|
+ service.longArticleMapper = longArticleMapper;
|
|
|
+ service.growthMapper = growthMapper;
|
|
|
+ service.redisClient = redisClient;
|
|
|
+ return service;
|
|
|
+ }
|
|
|
+}
|