liujie
10 小时以前 fddf3d913d47f391f84f9e460cb76d427ef02c44
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
package com.ruoyi.user.service.impl;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
 
import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
 
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.user.domain.AccountLevelConfig;
import com.ruoyi.user.mapper.AccountLevelConfigMapper;
 
/**
 * 等级配置服务单元测试
 *
 * 覆盖等级白名单(合法等级透传、非法/空等级拒绝且不落库)、读接口透传,
 * 以及开关缺省时的归一化(空 -> 关闭,避免库里出现 NULL 这一「第三种状态」)。
 *
 * @author hugray
 */
@ExtendWith(MockitoExtension.class)
class AccountLevelConfigServiceImplTest
{
    @Mock
    private AccountLevelConfigMapper levelConfigMapper;
 
    @InjectMocks
    private AccountLevelConfigServiceImpl levelConfigService;
 
    private static AccountLevelConfig configOf(String levelCode)
    {
        AccountLevelConfig config = new AccountLevelConfig();
        config.setLevelCode(levelCode);
        return config;
    }
 
    @Test
    @DisplayName("合法等级应透传给 mapper")
    void saveAccountLevelConfig_shouldPassThrough_whenLevelValid()
    {
        AccountLevelConfig config = configOf("L2");
        config.setBuyQualify(AccountLevelConfig.SWITCH_ON);
        config.setConsumeAmount(new BigDecimal("1000.00"));
        when(levelConfigMapper.saveAccountLevelConfig(any(AccountLevelConfig.class))).thenReturn(1);
 
        int rows = levelConfigService.saveAccountLevelConfig(config);
 
        assertEquals(1, rows);
        ArgumentCaptor<AccountLevelConfig> captor = ArgumentCaptor.forClass(AccountLevelConfig.class);
        verify(levelConfigMapper).saveAccountLevelConfig(captor.capture());
        assertEquals("L2", captor.getValue().getLevelCode());
        assertEquals(new BigDecimal("1000.00"), captor.getValue().getConsumeAmount());
    }
 
    @Test
    @DisplayName("等级不在 C/L1~L4 之内时应拒绝且不落库")
    void saveAccountLevelConfig_shouldThrow_whenLevelUnknown()
    {
        ServiceException ex = assertThrows(ServiceException.class,
            () -> levelConfigService.saveAccountLevelConfig(configOf("L5")));
        assertEquals("等级不合法:L5", ex.getMessage());
        // 放过自由值等于允许客户端造出第 6 个等级行,而前端只有 5 个 Tab 能显示它
        verify(levelConfigMapper, never()).saveAccountLevelConfig(any(AccountLevelConfig.class));
    }
 
    @Test
    @DisplayName("等级为空时应拒绝且不落库")
    void saveAccountLevelConfig_shouldThrow_whenLevelEmpty()
    {
        assertThrows(ServiceException.class,
            () -> levelConfigService.saveAccountLevelConfig(configOf(null)));
        verify(levelConfigMapper, never()).saveAccountLevelConfig(any(AccountLevelConfig.class));
    }
 
    @Test
    @DisplayName("开关为空时应按「关闭」落库")
    void saveAccountLevelConfig_shouldDefaultSwitchesToOff_whenBlank()
    {
        when(levelConfigMapper.saveAccountLevelConfig(any(AccountLevelConfig.class))).thenReturn(1);
 
        levelConfigService.saveAccountLevelConfig(configOf("C"));
 
        ArgumentCaptor<AccountLevelConfig> captor = ArgumentCaptor.forClass(AccountLevelConfig.class);
        verify(levelConfigMapper).saveAccountLevelConfig(captor.capture());
        AccountLevelConfig saved = captor.getValue();
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getBuyQualify());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getInviteWarehouseQualify());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getPublicQualify());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getConsumeAmountEnabled());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getRecruitQtyEnabled());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getRealNameAuthEnabled());
        assertEquals(AccountLevelConfig.SWITCH_OFF, saved.getSubjectAuthEnabled());
    }
 
    @Test
    @DisplayName("开关已显式填「开启」时不应被归一化覆盖")
    void saveAccountLevelConfig_shouldKeepSwitchOn_whenExplicitlyOn()
    {
        AccountLevelConfig config = configOf("L4");
        config.setBuyQualify(AccountLevelConfig.SWITCH_ON);
        when(levelConfigMapper.saveAccountLevelConfig(any(AccountLevelConfig.class))).thenReturn(1);
 
        levelConfigService.saveAccountLevelConfig(config);
 
        ArgumentCaptor<AccountLevelConfig> captor = ArgumentCaptor.forClass(AccountLevelConfig.class);
        verify(levelConfigMapper).saveAccountLevelConfig(captor.capture());
        assertEquals(AccountLevelConfig.SWITCH_ON, captor.getValue().getBuyQualify());
    }
 
    @Test
    @DisplayName("查询接口应透传 mapper 结果")
    void selectAccountLevelConfigList_shouldPassThrough()
    {
        List<AccountLevelConfig> rows = Collections.singletonList(configOf("C"));
        when(levelConfigMapper.selectAccountLevelConfigList()).thenReturn(rows);
 
        assertEquals(rows, levelConfigService.selectAccountLevelConfigList());
    }
}