All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 27s
Docker Build & Deploy / Deploy to Production (push) Successful in 9s
Docker Build & Deploy / Cleanup Dangling Images (push) Successful in 2s
Docker Build & Deploy / WeChat Notification (push) Successful in 2s
609 lines
21 KiB
C#
609 lines
21 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using Service.Transaction;
|
||
|
||
namespace WebApi.Test.Transaction;
|
||
|
||
public class TransactionPeriodicServiceTest : BaseTest
|
||
{
|
||
private readonly ITransactionPeriodicRepository _periodicRepository = Substitute.For<ITransactionPeriodicRepository>();
|
||
private readonly ITransactionRecordRepository _transactionRepository = Substitute.For<ITransactionRecordRepository>();
|
||
private readonly IMessageRecordRepository _messageRepository = Substitute.For<IMessageRecordRepository>();
|
||
private readonly ILogger<TransactionPeriodicService> _logger = Substitute.For<ILogger<TransactionPeriodicService>>();
|
||
private readonly ITransactionPeriodicService _service;
|
||
|
||
public TransactionPeriodicServiceTest()
|
||
{
|
||
_service = new TransactionPeriodicService(
|
||
_periodicRepository,
|
||
_transactionRepository,
|
||
_messageRepository,
|
||
_logger
|
||
);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_每日账单()
|
||
{
|
||
// Arrange
|
||
var today = new DateTime(2024, 1, 15, 10, 0, 0);
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(1).AddAsync(Arg.Is<TransactionRecord>(t =>
|
||
t.Amount == -100m &&
|
||
t.Type == TransactionType.Expense &&
|
||
t.Classify == "餐饮" &&
|
||
t.Reason == "每日餐费" &&
|
||
t.Card == "周期性账单" &&
|
||
t.ImportFrom == "周期性账单自动生成"
|
||
));
|
||
|
||
await _messageRepository.Received(1).AddAsync(Arg.Is<MessageRecord>(m =>
|
||
m.Title == "周期性账单提醒" &&
|
||
m.Content.Contains("支出") &&
|
||
m.Content.Contains("100.00") &&
|
||
m.Content.Contains("每日餐费") &&
|
||
m.IsRead == false
|
||
));
|
||
|
||
await _periodicRepository.Received(1).UpdateExecuteTimeAsync(
|
||
Arg.Is(1L),
|
||
Arg.Is<DateTime>(dt => dt.Date == today.Date),
|
||
Arg.Is<DateTime?>(dt => dt.HasValue && dt.Value.Date == today.Date.AddDays(1))
|
||
);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_每周账单()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Weekly,
|
||
PeriodicConfig = "1,3,5", // 周一、三、五
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每周通勤费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 10, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(1).AddAsync(Arg.Is<TransactionRecord>(t =>
|
||
t.Amount == -200m &&
|
||
t.Type == TransactionType.Expense &&
|
||
t.Classify == "交通" &&
|
||
t.Reason == "每周通勤费"
|
||
));
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_每月账单()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Monthly,
|
||
PeriodicConfig = "1,15", // 每月1号和15号
|
||
Amount = 5000m,
|
||
Type = TransactionType.Income,
|
||
Classify = "工资",
|
||
Reason = "每月工资",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 1, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(1).AddAsync(Arg.Is<TransactionRecord>(t =>
|
||
t.Amount == 5000m &&
|
||
t.Type == TransactionType.Income &&
|
||
t.Classify == "工资" &&
|
||
t.Reason == "每月工资"
|
||
));
|
||
|
||
await _messageRepository.Received(1).AddAsync(Arg.Is<MessageRecord>(m =>
|
||
m.Content.Contains("收入") &&
|
||
m.Content.Contains("5000.00") &&
|
||
m.Content.Contains("每月工资")
|
||
));
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_未达到执行时间()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Weekly,
|
||
PeriodicConfig = "1,3,5", // 只在周一(1)、三(3)、五(5)执行
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每周通勤费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 10, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(0).AddAsync(Arg.Any<TransactionRecord>());
|
||
await _messageRepository.Received(0).AddAsync(Arg.Any<MessageRecord>());
|
||
await _periodicRepository.Received(0).UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>());
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_今天已执行过()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 15, 8, 0, 0), // 今天已经执行过
|
||
NextExecuteTime = new DateTime(2024, 1, 16, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
// 由于 LastExecuteTime 日期是今天,所以不会再次执行
|
||
await _transactionRepository.Received(0).AddAsync(Arg.Any<TransactionRecord>());
|
||
await _messageRepository.Received(0).AddAsync(Arg.Any<MessageRecord>());
|
||
await _periodicRepository.Received(0).UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>());
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_从未执行过()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Weekly,
|
||
PeriodicConfig = "1,3,5",
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每周通勤费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = null, // 从未执行过
|
||
NextExecuteTime = null
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(1).AddAsync(Arg.Any<TransactionRecord>());
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_添加交易记录失败()
|
||
{
|
||
// Arrange
|
||
var periodicBill = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(new[] { periodicBill });
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(false); // 添加失败
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _messageRepository.Received(0).AddAsync(Arg.Any<MessageRecord>());
|
||
await _periodicRepository.Received(0).UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>());
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_多条账单()
|
||
{
|
||
// Arrange
|
||
var periodicBills = new[]
|
||
{
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
},
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 2,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每日交通",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
}
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(periodicBills);
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
await _transactionRepository.Received(2).AddAsync(Arg.Any<TransactionRecord>());
|
||
await _messageRepository.Received(2).AddAsync(Arg.Any<MessageRecord>());
|
||
await _periodicRepository.Received(2).UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>());
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每日()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
PeriodicConfig = ""
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 15, 10, 0, 0);
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 1, 16, 0, 0, 0));
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每周_本周内()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Weekly,
|
||
PeriodicConfig = "1,3,5" // 周一、三、五
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 15, 10, 0, 0); // 周一
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 1, 17, 0, 0, 0)); // 下周三
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每周_跨周()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Weekly,
|
||
PeriodicConfig = "1,3,5" // 周一、三、五
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 19, 10, 0, 0); // 周五
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 1, 22, 0, 0, 0)); // 下周一
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每月_本月内()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Monthly,
|
||
PeriodicConfig = "1,15" // 每月1号和15号
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 10, 10, 0, 0);
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 1, 15, 0, 0, 0));
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每月_跨月()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Monthly,
|
||
PeriodicConfig = "1,15" // 每月1号和15号
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 16, 10, 0, 0);
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 2, 1, 0, 0, 0));
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每月_月末()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Monthly,
|
||
PeriodicConfig = "30,31" // 每月30号和31号
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 15, 10, 0, 0); // 1月只有31天
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 1, 30, 0, 0, 0));
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每月_小月()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Monthly,
|
||
PeriodicConfig = "30,31" // 每月30号和31号
|
||
};
|
||
var baseTime = new DateTime(2024, 4, 25, 10, 0, 0); // 4月只有30天
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 4, 30, 0, 0, 0)); // 30号,31号不存在
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每季度()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Quarterly,
|
||
PeriodicConfig = "15" // 每季度第15天
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 15, 10, 0, 0);
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2024, 4, 15, 0, 0, 0)); // 下季度
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_每年()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Yearly,
|
||
PeriodicConfig = "100" // 每年第100天
|
||
};
|
||
var baseTime = new DateTime(2024, 4, 10, 10, 0, 0); // 第100天是4月9日
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().Be(new DateTime(2025, 4, 9, 0, 0, 0)); // 下一年
|
||
}
|
||
|
||
[Fact]
|
||
public void CalculateNextExecuteTime_未知周期类型()
|
||
{
|
||
// Arrange
|
||
var periodic = new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = (PeriodicType)99, // 未知类型
|
||
PeriodicConfig = ""
|
||
};
|
||
var baseTime = new DateTime(2024, 1, 15, 10, 0, 0);
|
||
|
||
// Act
|
||
var result = _service.CalculateNextExecuteTime(periodic, baseTime);
|
||
|
||
// Assert
|
||
result.Should().BeNull();
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_处理异常不中断()
|
||
{
|
||
// Arrange
|
||
var periodicBills = new[]
|
||
{
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
},
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 2,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每日交通",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
}
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(periodicBills);
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(args =>
|
||
{
|
||
var id = (long)args[0];
|
||
if (id == 1)
|
||
{
|
||
throw new Exception("更新失败");
|
||
}
|
||
return Task.CompletedTask;
|
||
});
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
// 第二条记录应该成功处理
|
||
await _transactionRepository.Received(2).AddAsync(Arg.Any<TransactionRecord>());
|
||
}
|
||
|
||
[Fact]
|
||
public async Task ExecutePeriodicBillsAsync_处理所有账单()
|
||
{
|
||
// Arrange
|
||
var periodicBills = new[]
|
||
{
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 1,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 100m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "餐饮",
|
||
Reason = "每日餐费",
|
||
IsEnabled = false, // 禁用
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
},
|
||
new TransactionPeriodic
|
||
{
|
||
Id = 2,
|
||
PeriodicType = PeriodicType.Daily,
|
||
Amount = 200m,
|
||
Type = TransactionType.Expense,
|
||
Classify = "交通",
|
||
Reason = "每日交通",
|
||
IsEnabled = true,
|
||
LastExecuteTime = new DateTime(2024, 1, 14, 10, 0, 0),
|
||
NextExecuteTime = new DateTime(2024, 1, 15, 10, 0, 0)
|
||
}
|
||
};
|
||
|
||
_periodicRepository.GetPendingPeriodicBillsAsync().Returns(periodicBills);
|
||
_transactionRepository.AddAsync(Arg.Any<TransactionRecord>()).Returns(Task.FromResult(true));
|
||
_messageRepository.AddAsync(Arg.Any<MessageRecord>()).Returns(Task.CompletedTask);
|
||
_periodicRepository.UpdateExecuteTimeAsync(Arg.Any<long>(), Arg.Any<DateTime>(), Arg.Any<DateTime>())
|
||
.Returns(Task.CompletedTask);
|
||
|
||
// Act
|
||
await _service.ExecutePeriodicBillsAsync();
|
||
|
||
// Assert
|
||
// 只有启用的账单会被处理
|
||
await _transactionRepository.Received(1).AddAsync(Arg.Is<TransactionRecord>(t => t.Reason == "每日交通"));
|
||
await _transactionRepository.Received(0).AddAsync(Arg.Is<TransactionRecord>(t => t.Reason == "每日餐费"));
|
||
}
|
||
}
|