using Service.Budget; namespace WebApi.Test.Budget; /// /// BudgetItemCalculator 单元测试 /// 测试明细项计算用金额的各种规则 /// public class BudgetItemCalculatorTest : BaseTest { [Fact] public void 收入项实际已发生_应返回实际值() { // Arrange var budgetLimit = 10000m; var actualAmount = 9500m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Income, budgetLimit, actualAmount, isMandatory: false, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(9500m); } [Fact] public void 收入项实际未发生_应返回预算值() { // Arrange var budgetLimit = 5000m; var actualAmount = 0m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Income, budgetLimit, actualAmount, isMandatory: false, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(5000m); } [Fact] public void 支出项普通情况_应返回MAX预算和实际() { // Arrange var budgetLimit = 2000m; var actualAmount = 2500m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: false, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(2500m); } [Fact] public void 支出项未超预算_应返回预算值() { // Arrange var budgetLimit = 2000m; var actualAmount = 1800m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: false, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(2000m); } [Fact] public void 支出项超预算_应返回实际值() { // Arrange var budgetLimit = 2000m; var actualAmount = 2500m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: false, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(2500m); } [Fact] public void 支出项硬性且实际为0_月度_应按天数折算() { // Arrange var budgetLimit = 3000m; var actualAmount = 0m; var date = new DateTime(2026, 2, 15); // 2月共28天,当前15号 // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: true, isArchived: false, date, BudgetPeriodType.Month ); // Assert var expected = 3000m / 28 * 15; // ≈ 1607.14 result.Should().BeApproximately(expected, 0.01m); } [Fact] public void 支出项硬性且实际为0_年度_应按天数折算() { // Arrange var budgetLimit = 12000m; var actualAmount = 0m; var date = new DateTime(2026, 2, 15); // 2026年第46天(31+15) // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: true, isArchived: false, date, BudgetPeriodType.Year ); // Assert var expected = 12000m / 365 * 46; // ≈ 1512.33 result.Should().BeApproximately(expected, 0.01m); } [Fact] public void 支出项硬性且实际大于0_应返回MAX值() { // Arrange var budgetLimit = 3000m; var actualAmount = 3200m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: true, isArchived: false, new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(3200m); } [Fact] public void 归档数据_应直接返回实际值() { // Arrange var budgetLimit = 2000m; var actualAmount = 1800m; // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: false, isArchived: true, // 归档数据 new DateTime(2026, 2, 15), BudgetPeriodType.Month ); // Assert result.Should().Be(1800m); // 归档数据直接返回实际值,不走MAX逻辑 } [Fact] public void 闰年2月按天折算边界情况() { // Arrange var budgetLimit = 3000m; var actualAmount = 0m; var date = new DateTime(2024, 2, 29); // 闰年2月29日 // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: true, isArchived: false, date, BudgetPeriodType.Month ); // Assert var expected = 3000m / 29 * 29; // = 3000 result.Should().Be(expected); } [Fact] public void 平年2月按天折算边界情况() { // Arrange var budgetLimit = 3000m; var actualAmount = 0m; var date = new DateTime(2026, 2, 28); // 平年2月28日 // Act var result = BudgetItemCalculator.CalculateEffectiveAmount( BudgetCategory.Expense, budgetLimit, actualAmount, isMandatory: true, isArchived: false, date, BudgetPeriodType.Month ); // Assert var expected = 3000m / 28 * 28; // = 3000 result.Should().Be(expected); } }