feat(catalog): 新增分类推荐榜快照接口
backend-ci / test (push) Failing after 4m45s

This commit is contained in:
Zhou Weidong committed 2026-11-02 14:45:43 +08:00
1 parent afd8d00752
commit 8a5a381b44
23 files changed
+793 -16

No files matched your search

@@ -3,6 +3,7 @@ package com.fruitshorts.app.controller;
import com.fruitshorts.app.service.AppCatalogService;
import com.fruitshorts.app.service.AppEpisodeStatsService;
import com.fruitshorts.app.service.AppRankingService;
import com.fruitshorts.app.support.ControllerContractSupport;
import com.fruitshorts.app.vo.AppBannerVO;
import com.fruitshorts.app.vo.AppCategoryVO;
@@ -10,6 +11,8 @@ import com.fruitshorts.app.vo.AppDramaCardVO;
import com.fruitshorts.app.vo.AppDramaDetailVO;
import com.fruitshorts.app.vo.AppFeedVO;
import com.fruitshorts.app.vo.AppSectionVO;
import com.fruitshorts.app.vo.AppRankingEntryVO;
import com.fruitshorts.app.vo.AppRankingVO;
import com.fruitshorts.common.pojo.CursorResult;
import com.fruitshorts.content.service.EpisodeService;
import com.fruitshorts.common.exception.ErrorCode;
@@ -41,13 +44,16 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
class AppCatalogControllerContractTest {
private AppCatalogService catalogService;
private AppRankingService rankingService;
private MockMvc catalogMvc;
private MockMvc dramaMvc;
@BeforeEach
void setUp() {
catalogService = mock(AppCatalogService.class);
catalogMvc = ControllerContractSupport.mockMvcOf(new AppCatalogController(catalogService));
rankingService = mock(AppRankingService.class);
catalogMvc = ControllerContractSupport.mockMvcOf(
new AppCatalogController(catalogService, rankingService));
dramaMvc = ControllerContractSupport.mockMvcOf(
new AppDramaController(catalogService, mock(PlaybackService.class),
mock(EpisodeService.class), mock(CommentService.class),
@@ -122,15 +128,44 @@ class AppCatalogControllerContractTest {
@Test
void should_return_category_list_when_categories_are_requested() throws Exception {
AppCategoryVO category = new AppCategoryVO(3L, "都市");
category.setCode("RECOMMEND_RANKING");
category.setLayoutType("RANKING");
category.setRevision(7L);
given(catalogService.categories()).willReturn(List.of(category));
catalogMvc.perform(get("/app/categories"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data[0].id").value(3))
.andExpect(jsonPath("$.data[0].code").value("RECOMMEND_RANKING"))
.andExpect(jsonPath("$.data[0].layoutType").value("RANKING"))
.andExpect(jsonPath("$.data[0].revision").value("7"))
.andExpect(jsonPath("$.data[0].locales.zh").value("都市"));
}
@Test
void should_return_server_rank_when_ranking_is_requested() throws Exception {
AppDramaCardVO card = new AppDramaCardVO();
card.setId(12L);
card.setTitleLocales(Map.of("zh", "榜首短剧"));
AppRankingVO ranking = new AppRankingVO();
ranking.setId(3L);
ranking.setCode("RECOMMEND_RANKING");
ranking.setRevision(8L);
ranking.setTotal(1);
ranking.setList(List.of(new AppRankingEntryVO(1, card)));
given(rankingService.ranking(3L)).willReturn(ranking);
catalogMvc.perform(get("/app/categories/3/ranking"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data.revision").value("8"))
.andExpect(jsonPath("$.data.list[0].rank").value(1))
.andExpect(jsonPath("$.data.list[0].drama.id").value("12"));
verify(rankingService).ranking(3L);
}
@Test
void should_bind_path_variable_when_drama_detail_is_requested() throws Exception {
AppDramaDetailVO detail = new AppDramaDetailVO();
@@ -328,7 +328,9 @@ class AppCommentCountAnonymousSecurityTest {
@Bean
AppCatalogController appCatalogController(AppCatalogService appCatalogService) {
return new AppCatalogController(appCatalogService);
return new AppCatalogController(
appCatalogService,
mock(com.fruitshorts.app.service.AppRankingService.class));
}
@Bean
@@ -0,0 +1,75 @@
// Author: fruit.com.cn
package com.fruitshorts.app.service;
import com.fruitshorts.app.vo.AppDramaCardVO;
import com.fruitshorts.app.vo.AppRankingVO;
import com.fruitshorts.content.dal.entity.Drama;
import com.fruitshorts.content.dal.entity.DramaClassification;
import com.fruitshorts.content.service.DramaClassificationService;
import com.fruitshorts.content.service.DramaService;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/** 推荐榜快照顺序与排名测试。 */
class AppRankingServiceTest {
@Test
void should_preserve_server_order_and_compact_rank_when_offline_items_are_filtered() {
DramaClassificationService classificationService = mock(DramaClassificationService.class);
DramaService dramaService = mock(DramaService.class);
AppCatalogService catalogService = mock(AppCatalogService.class);
AppRankingService service = new AppRankingService(
classificationService, dramaService, catalogService);
DramaClassification classification = rankingClassification();
Drama second = drama(22L);
Drama first = drama(11L);
given(classificationService.getEnabledById(3L)).willReturn(classification);
given(classificationService.listDramaIdsByClassification(3L))
.willReturn(List.of(11L, 99L, 22L));
given(dramaService.listPublishedByIds(List.of(11L, 99L, 22L)))
.willReturn(List.of(second, first));
AppDramaCardVO firstCard = card(11L);
AppDramaCardVO secondCard = card(22L);
given(catalogService.toCards(List.of(first, second)))
.willReturn(List.of(firstCard, secondCard));
AppRankingVO result = service.ranking(3L);
assertThat(result.getRevision()).isEqualTo(7L);
assertThat(result.getList()).extracting(item -> item.getDrama().getId())
.containsExactly(11L, 22L);
assertThat(result.getList()).extracting(item -> item.getRank())
.containsExactly(1, 2);
}
private DramaClassification rankingClassification() {
DramaClassification classification = new DramaClassification();
classification.setId(3L);
classification.setCode("RECOMMEND_RANKING");
classification.setName("推荐榜");
classification.setNameLocales("{\"zh\":\"推荐榜\"}");
classification.setLayoutType(DramaClassificationService.LAYOUT_RANKING);
classification.setRevision(7L);
return classification;
}
private Drama drama(Long id) {
Drama drama = new Drama();
drama.setId(id);
return drama;
}
private AppDramaCardVO card(Long id) {
AppDramaCardVO card = new AppDramaCardVO();
card.setId(id);
card.setTitleLocales(Map.of("zh", "短剧" + id));
return card;
}
}