|
|
@@ -1,227 +0,0 @@
|
|
|
-package com.bex.staking.engine;
|
|
|
-
|
|
|
-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 com.bex.staking.constant.StakingErrorCode;
|
|
|
-import com.bex.staking.enums.SubscriptionMode;
|
|
|
-import com.bex.staking.exception.StakingException;
|
|
|
-import java.math.BigDecimal;
|
|
|
-import java.util.List;
|
|
|
-import org.junit.jupiter.api.DisplayName;
|
|
|
-import org.junit.jupiter.api.Nested;
|
|
|
-import org.junit.jupiter.api.Test;
|
|
|
-
|
|
|
-/**
|
|
|
- * {@link SubscriptionValidator} 认购额度校验器单元测试。
|
|
|
- *
|
|
|
- * <p>覆盖固定档位、无限制区间与通用最小下限三类校验的典型场景与边界值(需求 5.2、5.3、5.4、5.5、12.1、12.2)。
|
|
|
- */
|
|
|
-class SubscriptionValidatorTest {
|
|
|
-
|
|
|
- private static final String TIER_CONFIG = "[1000,5000,10000]";
|
|
|
-
|
|
|
- @Nested
|
|
|
- @DisplayName("固定档位(FIXED)额度校验")
|
|
|
- class FixedModeTests {
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量等于某一档位时通过")
|
|
|
- void passesWhenAmountEqualsTier() {
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("5000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("10000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量等于档位但标度不同(1000.00)时通过")
|
|
|
- void passesWhenAmountEqualsTierWithDifferentScale() {
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1000.00"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量不等于任何档位时不通过")
|
|
|
- void failsWhenAmountNotInTiers() {
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("2000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("档位配置为空时不通过")
|
|
|
- void failsWhenTierConfigBlank() {
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1000"), SubscriptionMode.FIXED, "", null, null));
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1000"), SubscriptionMode.FIXED, null, null, null));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Nested
|
|
|
- @DisplayName("无限制区间(UNLIMITED)额度校验")
|
|
|
- class UnlimitedModeTests {
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量落在区间内时通过")
|
|
|
- void passesWhenWithinRange() {
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("500"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量等于区间边界时通过")
|
|
|
- void passesAtRangeBoundaries() {
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("100"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- assertTrue(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1000"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量超过上限时不通过")
|
|
|
- void failsWhenAboveMax() {
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("1001"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量低于区间下限(且 ≥100 最小值)时不通过")
|
|
|
- void failsWhenBelowMin() {
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("150"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("200"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Nested
|
|
|
- @DisplayName("通用最小下限(100 BEX)校验")
|
|
|
- class MinimumTests {
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量为 100 时满足最小下限")
|
|
|
- void meetsMinimumAt100() {
|
|
|
- assertTrue(SubscriptionValidator.meetsMinimum(new BigDecimal("100")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量为 99.999... 时不满足最小下限")
|
|
|
- void failsBelow100() {
|
|
|
- assertFalse(SubscriptionValidator.meetsMinimum(new BigDecimal("99.999999999999999999")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("无限制模式下数量低于 100 即使落在区间内也不通过")
|
|
|
- void failsWhenBelowGlobalMinimumEvenIfInRange() {
|
|
|
- assertFalse(SubscriptionValidator.isValid(
|
|
|
- new BigDecimal("50"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("10"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("空数量不满足最小下限")
|
|
|
- void failsWhenNull() {
|
|
|
- assertFalse(SubscriptionValidator.meetsMinimum(null));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Nested
|
|
|
- @DisplayName("tier_config JSON 解析")
|
|
|
- class ParseTiersTests {
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("正常解析档位数组")
|
|
|
- void parsesValidArray() {
|
|
|
- List<BigDecimal> tiers = SubscriptionValidator.parseTiers(TIER_CONFIG);
|
|
|
- assertEquals(3, tiers.size());
|
|
|
- assertEquals(0, new BigDecimal("1000").compareTo(tiers.get(0)));
|
|
|
- assertEquals(0, new BigDecimal("10000").compareTo(tiers.get(2)));
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("非法 JSON 返回空列表")
|
|
|
- void returnsEmptyOnInvalidJson() {
|
|
|
- assertTrue(SubscriptionValidator.parseTiers("not-json").isEmpty());
|
|
|
- assertTrue(SubscriptionValidator.parseTiers("").isEmpty());
|
|
|
- assertTrue(SubscriptionValidator.parseTiers(null).isEmpty());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- @Nested
|
|
|
- @DisplayName("业务层封装 validate:抛出 StakingException(40003)")
|
|
|
- class ValidateThrowsTests {
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("数量低于 100 抛出 40003")
|
|
|
- void throwsWhenBelowMinimum() {
|
|
|
- StakingException ex = assertThrows(
|
|
|
- StakingException.class,
|
|
|
- () -> SubscriptionValidator.validate(
|
|
|
- new BigDecimal("99"), SubscriptionMode.UNLIMITED, null, BigDecimal.ZERO, new BigDecimal("1000")));
|
|
|
- assertEquals(StakingErrorCode.INVALID_AMOUNT, ex.getCode());
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("固定档位不匹配抛出 40003")
|
|
|
- void throwsWhenTierNotMatched() {
|
|
|
- StakingException ex = assertThrows(
|
|
|
- StakingException.class,
|
|
|
- () -> SubscriptionValidator.validate(
|
|
|
- new BigDecimal("2000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null));
|
|
|
- assertEquals(StakingErrorCode.INVALID_AMOUNT, ex.getCode());
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("无限制区间越界抛出 40003")
|
|
|
- void throwsWhenOutOfRange() {
|
|
|
- StakingException ex = assertThrows(
|
|
|
- StakingException.class,
|
|
|
- () -> SubscriptionValidator.validate(
|
|
|
- new BigDecimal("5000"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000")));
|
|
|
- assertEquals(StakingErrorCode.INVALID_AMOUNT, ex.getCode());
|
|
|
- }
|
|
|
-
|
|
|
- @Test
|
|
|
- @DisplayName("合法数量不抛异常")
|
|
|
- void doesNotThrowWhenValid() {
|
|
|
- SubscriptionValidator.validate(
|
|
|
- new BigDecimal("1000"), SubscriptionMode.FIXED, TIER_CONFIG, null, null);
|
|
|
- SubscriptionValidator.validate(
|
|
|
- new BigDecimal("500"),
|
|
|
- SubscriptionMode.UNLIMITED,
|
|
|
- null,
|
|
|
- new BigDecimal("100"),
|
|
|
- new BigDecimal("1000"));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|