fix
This commit is contained in:
352
WebApi.Test/Application/TransactionPeriodicApplicationTest.cs
Normal file
352
WebApi.Test/Application/TransactionPeriodicApplicationTest.cs
Normal file
@@ -0,0 +1,352 @@
|
||||
using Application.Dto.Periodic;
|
||||
using Service.Transaction;
|
||||
|
||||
namespace WebApi.Test.Application;
|
||||
|
||||
/// <summary>
|
||||
/// TransactionPeriodicApplication 单元测试
|
||||
/// </summary>
|
||||
public class TransactionPeriodicApplicationTest : BaseApplicationTest
|
||||
{
|
||||
private readonly ITransactionPeriodicRepository _periodicRepository;
|
||||
private readonly ITransactionPeriodicService _periodicService;
|
||||
private readonly ILogger<TransactionPeriodicApplication> _logger;
|
||||
private readonly TransactionPeriodicApplication _application;
|
||||
|
||||
public TransactionPeriodicApplicationTest()
|
||||
{
|
||||
_periodicRepository = Substitute.For<ITransactionPeriodicRepository>();
|
||||
_periodicService = Substitute.For<ITransactionPeriodicService>();
|
||||
_logger = CreateMockLogger<TransactionPeriodicApplication>();
|
||||
_application = new TransactionPeriodicApplication(_periodicRepository, _periodicService, _logger);
|
||||
}
|
||||
|
||||
#region GetListAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task GetListAsync_有数据_应返回分页结果()
|
||||
{
|
||||
// Arrange
|
||||
var pageIndex = 1;
|
||||
var pageSize = 10;
|
||||
var periodics = new List<TransactionPeriodic>
|
||||
{
|
||||
new() { Id = 1, Amount = 100, Type = TransactionType.Expense, Classify = "房租", IsEnabled = true },
|
||||
new() { Id = 2, Amount = 5000, Type = TransactionType.Income, Classify = "工资", IsEnabled = true }
|
||||
};
|
||||
_periodicRepository.GetPagedListAsync(pageIndex, pageSize, null).Returns(periodics);
|
||||
_periodicRepository.GetTotalCountAsync(null).Returns(2L);
|
||||
|
||||
// Act
|
||||
var result = await _application.GetListAsync(pageIndex, pageSize);
|
||||
|
||||
// Assert
|
||||
result.Data.Should().HaveCount(2);
|
||||
result.Total.Should().Be(2);
|
||||
result.Data[0].Amount.Should().Be(100);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetListAsync_带搜索关键词_应过滤结果()
|
||||
{
|
||||
// Arrange
|
||||
var keyword = "房租";
|
||||
var periodics = new List<TransactionPeriodic>
|
||||
{
|
||||
new() { Id = 1, Amount = 1000, Type = TransactionType.Expense, Classify = "房租", IsEnabled = true }
|
||||
};
|
||||
_periodicRepository.GetPagedListAsync(1, 20, keyword).Returns(periodics);
|
||||
_periodicRepository.GetTotalCountAsync(keyword).Returns(1L);
|
||||
|
||||
// Act
|
||||
var result = await _application.GetListAsync(1, 20, keyword);
|
||||
|
||||
// Assert
|
||||
result.Data.Should().HaveCount(1);
|
||||
result.Total.Should().Be(1);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetByIdAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_存在的记录_应返回详情()
|
||||
{
|
||||
// Arrange
|
||||
var periodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
Classify = "房租",
|
||||
Reason = "每月房租",
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(periodic);
|
||||
|
||||
// Act
|
||||
var result = await _application.GetByIdAsync(1);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result.Id.Should().Be(1);
|
||||
result.Amount.Should().Be(1000);
|
||||
result.Classify.Should().Be("房租");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetByIdAsync_不存在的记录_应抛出NotFoundException()
|
||||
{
|
||||
// Arrange
|
||||
_periodicRepository.GetByIdAsync(999).Returns((TransactionPeriodic?)null);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => _application.GetByIdAsync(999));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CreateAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_有效请求_应成功创建()
|
||||
{
|
||||
// Arrange
|
||||
var request = new CreatePeriodicRequest
|
||||
{
|
||||
PeriodicType = PeriodicType.Monthly,
|
||||
PeriodicConfig = "1",
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
Classify = "房租",
|
||||
Reason = "每月房租"
|
||||
};
|
||||
var nextExecuteTime = DateTime.Now.AddDays(1);
|
||||
_periodicService.CalculateNextExecuteTime(Arg.Any<TransactionPeriodic>(), Arg.Any<DateTime>())
|
||||
.Returns(nextExecuteTime);
|
||||
_periodicRepository.AddAsync(Arg.Any<TransactionPeriodic>()).Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await _application.CreateAsync(request);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result.Amount.Should().Be(1000);
|
||||
result.IsEnabled.Should().BeTrue();
|
||||
await _periodicRepository.Received(1).AddAsync(Arg.Is<TransactionPeriodic>(
|
||||
p => p.Amount == 1000 && p.Classify == "房租"
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateAsync_Repository添加失败_应抛出BusinessException()
|
||||
{
|
||||
// Arrange
|
||||
var request = new CreatePeriodicRequest
|
||||
{
|
||||
PeriodicType = PeriodicType.Monthly,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense
|
||||
};
|
||||
_periodicService.CalculateNextExecuteTime(Arg.Any<TransactionPeriodic>(), Arg.Any<DateTime>())
|
||||
.Returns(DateTime.Now.AddDays(1));
|
||||
_periodicRepository.AddAsync(Arg.Any<TransactionPeriodic>()).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<BusinessException>(() => _application.CreateAsync(request));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region UpdateAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_有效请求_应成功更新()
|
||||
{
|
||||
// Arrange
|
||||
var existingPeriodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
Classify = "房租",
|
||||
IsEnabled = true
|
||||
};
|
||||
var request = new UpdatePeriodicRequest
|
||||
{
|
||||
Id = 1,
|
||||
PeriodicType = PeriodicType.Monthly,
|
||||
PeriodicConfig = "1",
|
||||
Amount = 1200,
|
||||
Type = TransactionType.Expense,
|
||||
Classify = "房租",
|
||||
Reason = "房租涨价",
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(existingPeriodic);
|
||||
_periodicService.CalculateNextExecuteTime(Arg.Any<TransactionPeriodic>(), Arg.Any<DateTime>())
|
||||
.Returns(DateTime.Now.AddMonths(1));
|
||||
_periodicRepository.UpdateAsync(Arg.Any<TransactionPeriodic>()).Returns(true);
|
||||
|
||||
// Act
|
||||
await _application.UpdateAsync(request);
|
||||
|
||||
// Assert
|
||||
await _periodicRepository.Received(1).UpdateAsync(Arg.Is<TransactionPeriodic>(
|
||||
p => p.Id == 1 && p.Amount == 1200 && p.Reason == "房租涨价"
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_记录不存在_应抛出NotFoundException()
|
||||
{
|
||||
// Arrange
|
||||
var request = new UpdatePeriodicRequest
|
||||
{
|
||||
Id = 999,
|
||||
PeriodicType = PeriodicType.Monthly,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(999).Returns((TransactionPeriodic?)null);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => _application.UpdateAsync(request));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateAsync_Repository更新失败_应抛出BusinessException()
|
||||
{
|
||||
// Arrange
|
||||
var existingPeriodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense
|
||||
};
|
||||
var request = new UpdatePeriodicRequest
|
||||
{
|
||||
Id = 1,
|
||||
PeriodicType = PeriodicType.Monthly,
|
||||
Amount = 1200,
|
||||
Type = TransactionType.Expense,
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(existingPeriodic);
|
||||
_periodicService.CalculateNextExecuteTime(Arg.Any<TransactionPeriodic>(), Arg.Any<DateTime>())
|
||||
.Returns(DateTime.Now.AddMonths(1));
|
||||
_periodicRepository.UpdateAsync(Arg.Any<TransactionPeriodic>()).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<BusinessException>(() => _application.UpdateAsync(request));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DeleteByIdAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteByIdAsync_成功删除_不应抛出异常()
|
||||
{
|
||||
// Arrange
|
||||
_periodicRepository.DeleteAsync(1).Returns(true);
|
||||
|
||||
// Act
|
||||
await _application.DeleteByIdAsync(1);
|
||||
|
||||
// Assert
|
||||
await _periodicRepository.Received(1).DeleteAsync(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteByIdAsync_删除失败_应抛出BusinessException()
|
||||
{
|
||||
// Arrange
|
||||
_periodicRepository.DeleteAsync(999).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<BusinessException>(() => _application.DeleteByIdAsync(999));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ToggleEnabledAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task ToggleEnabledAsync_禁用账单_应成功更新状态()
|
||||
{
|
||||
// Arrange
|
||||
var periodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(periodic);
|
||||
_periodicRepository.UpdateAsync(Arg.Any<TransactionPeriodic>()).Returns(true);
|
||||
|
||||
// Act
|
||||
await _application.ToggleEnabledAsync(1, false);
|
||||
|
||||
// Assert
|
||||
await _periodicRepository.Received(1).UpdateAsync(Arg.Is<TransactionPeriodic>(
|
||||
p => p.Id == 1 && p.IsEnabled == false
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToggleEnabledAsync_启用账单_应成功更新状态()
|
||||
{
|
||||
// Arrange
|
||||
var periodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
IsEnabled = false
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(periodic);
|
||||
_periodicRepository.UpdateAsync(Arg.Any<TransactionPeriodic>()).Returns(true);
|
||||
|
||||
// Act
|
||||
await _application.ToggleEnabledAsync(1, true);
|
||||
|
||||
// Assert
|
||||
await _periodicRepository.Received(1).UpdateAsync(Arg.Is<TransactionPeriodic>(
|
||||
p => p.Id == 1 && p.IsEnabled == true
|
||||
));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToggleEnabledAsync_记录不存在_应抛出NotFoundException()
|
||||
{
|
||||
// Arrange
|
||||
_periodicRepository.GetByIdAsync(999).Returns((TransactionPeriodic?)null);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => _application.ToggleEnabledAsync(999, false));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ToggleEnabledAsync_更新失败_应抛出BusinessException()
|
||||
{
|
||||
// Arrange
|
||||
var periodic = new TransactionPeriodic
|
||||
{
|
||||
Id = 1,
|
||||
Amount = 1000,
|
||||
Type = TransactionType.Expense,
|
||||
IsEnabled = true
|
||||
};
|
||||
_periodicRepository.GetByIdAsync(1).Returns(periodic);
|
||||
_periodicRepository.UpdateAsync(Arg.Any<TransactionPeriodic>()).Returns(false);
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<BusinessException>(() => _application.ToggleEnabledAsync(1, false));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user