xyc
昨天 7032f3fb2ff26256e776e04a9bc62c8fab14379a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.trafficaudit.holiday.service;
 
import com.trafficaudit.holiday.service.HolidayStatService.DailyMetrics;
import org.junit.jupiter.api.Test;
 
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.function.Function;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
 
class HolidayBulletinServiceTest {
 
    @Test
    void formatsTableRatiosAsSignedPercentages() throws Exception {
        HolidayBulletinService service = new HolidayBulletinService(null);
 
        assertEquals("-4.7%", ratio(service, "95.3", "100", 1));
        assertEquals("-4.4%", ratio(service, "95.551398", "100", 1));
        assertEquals("-4.5%", ratio(service, "95.551398", "100", 2));
        assertEquals("-0.1%", ratio(service, "99.955", "100", 2));
        assertEquals("0%", ratio(service, "99.955", "100", 1));
        assertEquals("6.7%", ratio(service, "106.649", "100", 2));
        assertEquals("6.6%", ratio(service, "106.649", "100", 1));
        assertEquals("1.0%", ratio(service, "101", "100", 1));
        assertEquals("0%", ratio(service, "100", "100", 1));
        assertEquals("0%", ratio(service, "10004", "10000", 1));
        assertEquals("—", ratio(service, "100", null, 1));
        assertEquals("—", ratio(service, "100", "0", 1));
    }
 
    @Test
    void comparesCivilAviationOnlyThroughCoveredDay() throws Exception {
        HolidayStatService stat = mock(HolidayStatService.class);
        HolidayBulletinService service = new HolidayBulletinService(stat);
 
        DailyMetrics current = new DailyMetrics();
        current.setYear(2026);
        current.setHolidayType("NATIONAL_DAY");
        current.setDayIndex(2);
 
        DailyMetrics coveredDay = new DailyMetrics();
        coveredDay.setCivilAviation(new BigDecimal("6.7482"));
        DailyMetrics missingDay = new DailyMetrics();
 
        when(stat.dailyMetrics(2026, "NATIONAL_DAY", 2)).thenReturn(missingDay);
        when(stat.dailyMetrics(2026, "NATIONAL_DAY", 1)).thenReturn(coveredDay);
 
        DailyMetrics previousYear = new DailyMetrics();
        previousYear.setYear(2025);
        DailyMetrics previousYearThroughDay1 = new DailyMetrics();
        previousYearThroughDay1.setCivilAviation(new BigDecimal("7.5003"));
        when(stat.cumulativeMetrics(2025, "NATIONAL_DAY", 1)).thenReturn(previousYearThroughDay1);
 
        Object result = comparableCumulative(service, current, previousYear, DailyMetrics::getCivilAviation);
 
        assertSame(previousYearThroughDay1, result);
        verify(stat).cumulativeMetrics(2025, "NATIONAL_DAY", 1);
        verify(stat, never()).cumulativeMetrics(2025, "NATIONAL_DAY", 2);
    }
 
    @Test
    void comparableCumulativeIsNullWhenCurrentYearHasNoMetricData() throws Exception {
        HolidayStatService stat = mock(HolidayStatService.class);
        HolidayBulletinService service = new HolidayBulletinService(stat);
 
        DailyMetrics current = new DailyMetrics();
        current.setYear(2026);
        current.setHolidayType("NATIONAL_DAY");
        current.setDayIndex(2);
        when(stat.dailyMetrics(2026, "NATIONAL_DAY", 2)).thenReturn(new DailyMetrics());
        when(stat.dailyMetrics(2026, "NATIONAL_DAY", 1)).thenReturn(new DailyMetrics());
 
        Object result = comparableCumulative(service, current, new DailyMetrics(), DailyMetrics::getCivilAviation);
 
        assertNull(result);
        verify(stat, never()).cumulativeMetrics(0, "NATIONAL_DAY", 1);
    }
 
    @Test
    void cumulativeParagraphUsesExcelDisplayThenBulletinRounding() throws Exception {
        HolidayBulletinService service = new HolidayBulletinService(null);
 
        DailyMetrics current = new DailyMetrics();
        current.setTotalPersonFlow(new BigDecimal("3088.62958"));
        DailyMetrics previousYear = new DailyMetrics();
        previousYear.setTotalPersonFlow(new BigDecimal("3232.42742"));
        DailyMetrics twoYearsAgo = new DailyMetrics();
        twoYearsAgo.setTotalPersonFlow(new BigDecimal("3137.80860"));
 
        Method method = HolidayBulletinService.class.getDeclaredMethod(
                "cumulativeParagraph", DailyMetrics.class, DailyMetrics.class, DailyMetrics.class);
        method.setAccessible(true);
        String text = (String) method.invoke(service, current, previousYear, twoYearsAgo);
 
        assertEquals(
                "假期以来,全省全社会跨区域人员流动量累计3088.63万人次,比2025年同期下降4.5%,比2024年同期下降1.6%。",
                text);
    }
 
    @Test
    void cumulativeAmountsUseExcelYiDisplayBeforeWanRounding() throws Exception {
        HolidayBulletinService service = new HolidayBulletinService(null);
 
        assertEquals("3961.77", cumulativeNumber(service, "3961.76472"));
        assertEquals("4189.32", cumulativeNumber(service, "4189.31472"));
        assertEquals("4486.63", cumulativeNumber(service, "4486.62652"));
    }
 
    private String cumulativeNumber(HolidayBulletinService service, String value) throws Exception {
        Method method = HolidayBulletinService.class.getDeclaredMethod("numberCumulative", BigDecimal.class);
        method.setAccessible(true);
        BigDecimal number = value == null ? null : new BigDecimal(value);
        return (String) method.invoke(service, number);
    }
 
    private Object comparableCumulative(HolidayBulletinService service, DailyMetrics current,
                                        DailyMetrics comparisonYear,
                                        Function<DailyMetrics, BigDecimal> selector) throws Exception {
        Method method = HolidayBulletinService.class.getDeclaredMethod(
                "comparableCumulative", DailyMetrics.class, DailyMetrics.class, Function.class);
        method.setAccessible(true);
        return method.invoke(service, current, comparisonYear, selector);
    }
 
    private String ratio(HolidayBulletinService service, String current, String base,
                         int excelPercentScale) throws Exception {
        Method method = HolidayBulletinService.class.getDeclaredMethod(
                "ratio", BigDecimal.class, BigDecimal.class, int.class);
        method.setAccessible(true);
        BigDecimal currentValue = current == null ? null : new BigDecimal(current);
        BigDecimal baseValue = base == null ? null : new BigDecimal(base);
        return (String) method.invoke(service, currentValue, baseValue, excelPercentScale);
    }
}