Forráskód Böngészése

test(recommend): CardDetailServiceImpl 单测(6 项:组装/无批次/不存在/空ID/period窗)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jintao.geng 1 hónapja
szülő
commit
cd1d072616

+ 153 - 0
mango-application/src/test/java/com/mangoo/rating/recommend/cart/CardDetailServiceImplTest.java

@@ -0,0 +1,153 @@
+package com.mangoo.rating.recommend.cart;
+
+import com.mangoo.rating.recommend.AjaxResult;
+import com.mangoo.rating.recommend.manager.ActiveBatchManager;
+import com.mangoo.rating.recommend.manager.CardPopManager;
+import com.mangoo.rating.recommend.manager.CardValueHistoryManager;
+import com.mangoo.rating.recommend.manager.RatingRecommendRuleManager;
+import com.mangoo.rating.recommend.po.CardPopPO;
+import com.mangoo.rating.recommend.po.CardValueHistoryPO;
+import com.mangoo.rating.recommend.po.RatingRecommendRulePO;
+import com.mangoo.rating.recommend.response.recommend.CardDetailVO;
+import com.mangoo.rating.recommend.service.impl.CardDetailServiceImpl;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * CardDetailServiceImpl Mockito 单测
+ *
+ * @author gengjintao
+ * @date 2026/06/25
+ */
+@ExtendWith(MockitoExtension.class)
+class CardDetailServiceImplTest {
+
+    @Mock
+    private RatingRecommendRuleManager ruleManager;
+    @Mock
+    private CardPopManager cardPopManager;
+    @Mock
+    private CardValueHistoryManager cardValueHistoryManager;
+    @Mock
+    private ActiveBatchManager activeBatchManager;
+    @InjectMocks
+    private CardDetailServiceImpl service;
+
+    @Captor
+    private ArgumentCaptor<LocalDate> dateCaptor;
+
+    @BeforeEach
+    void setUp() {
+        // 默认桩:有生效批次 B1,POP 与趋势默认空(lenient 避免未使用桩报错)
+        lenient().when(activeBatchManager.selectActiveBatchNo()).thenReturn("B1");
+        lenient().when(cardPopManager.selectByCardId(eq("C1"), eq("B1"))).thenReturn(Collections.emptyList());
+        lenient().when(cardValueHistoryManager.selectTrend(eq("C1"), org.mockito.ArgumentMatchers.any())).thenReturn(Collections.emptyList());
+    }
+
+    /** 构造一条标准规则 PO */
+    private RatingRecommendRulePO rule() {
+        RatingRecommendRulePO r = new RatingRecommendRulePO();
+        r.setCardId("C1");
+        r.setCardNo("066/080");
+        r.setPlayer("AIPOM");
+        r.setYear("2026");
+        r.setSeries("pokemon.M2.JNP");
+        r.setCardSet("BASE");
+        r.setCurrentValue(new BigDecimal("15"));
+        r.setValueChangePct(new BigDecimal("7.05"));
+        r.setValueMin(new BigDecimal("10"));
+        r.setValueMax(new BigDecimal("45"));
+        return r;
+    }
+
+    /** 取状态码(Map 风格,成功 0) */
+    private int code(AjaxResult r) {
+        return ((Number) r.get("code")).intValue();
+    }
+
+    /** 取 data(Map 风格) */
+    private CardDetailVO data(AjaxResult r) {
+        return (CardDetailVO) r.get("data");
+    }
+
+    @Test
+    void 正常_组装详情() {
+        when(ruleManager.selectByCardId("C1", "B1")).thenReturn(rule());
+        CardPopPO pop = new CardPopPO();
+        pop.setCardId("C1");
+        pop.setAgency("PSA");
+        pop.setGradeAll(660);
+        pop.setGrade10(25);
+        when(cardPopManager.selectByCardId("C1", "B1")).thenReturn(Collections.singletonList(pop));
+        CardValueHistoryPO h = new CardValueHistoryPO();
+        h.setCardId("C1");
+        h.setPrice(new BigDecimal("12"));
+        h.setRecordDate(LocalDate.now().minusDays(1));
+        when(cardValueHistoryManager.selectTrend(eq("C1"), org.mockito.ArgumentMatchers.any())).thenReturn(Arrays.asList(h));
+
+        AjaxResult result = service.getDetail("C1", "30d");
+        assertEquals(0, code(result));
+        CardDetailVO d = data(result);
+        assertEquals("AIPOM", d.getName());
+        assertEquals("066/080", d.getCardNo());
+        assertEquals(new BigDecimal("15"), d.getValue().getCurrent());
+        assertEquals(1, d.getPops().size());
+        assertEquals("PSA", d.getPops().get(0).getAgency());
+        assertEquals(1, d.getTrend().size());
+    }
+
+    @Test
+    void 无生效批次_返回error() {
+        when(activeBatchManager.selectActiveBatchNo()).thenReturn(null);
+        AjaxResult result = service.getDetail("C1", "30d");
+        assertNotEquals(0, code(result));
+    }
+
+    @Test
+    void 卡片不存在_返回error() {
+        when(ruleManager.selectByCardId("C1", "B1")).thenReturn(null);
+        AjaxResult result = service.getDetail("C1", "30d");
+        assertNotEquals(0, code(result));
+    }
+
+    @Test
+    void cardId为空_返回error() {
+        AjaxResult result = service.getDetail("  ", "30d");
+        assertNotEquals(0, code(result));
+    }
+
+    @Test
+    void period_7d_起始为7天前() {
+        when(ruleManager.selectByCardId("C1", "B1")).thenReturn(rule());
+        service.getDetail("C1", "7d");
+        verify(cardValueHistoryManager).selectTrend(eq("C1"), dateCaptor.capture());
+        assertEquals(LocalDate.now().minusDays(7), dateCaptor.getValue());
+    }
+
+    @Test
+    void period_all_起始为null() {
+        when(ruleManager.selectByCardId("C1", "B1")).thenReturn(rule());
+        service.getDetail("C1", "all");
+        verify(cardValueHistoryManager).selectTrend(eq("C1"), isNull());
+    }
+}