Files
TakeoutSaaS.AdminApi/tests/TakeoutSaaS.Application.Tests/App/Tenants/Handlers/GetTenantsAnnouncementsQueryHandlerTests.cs

123 lines
4.9 KiB
C#

using FluentAssertions;
using Moq;
using TakeoutSaaS.Application.App.Tenants.Handlers;
using TakeoutSaaS.Application.App.Tenants.Queries;
using TakeoutSaaS.Application.Tests.TestUtilities;
using TakeoutSaaS.Domain.Tenants.Repositories;
namespace TakeoutSaaS.Application.Tests.App.Tenants.Handlers;
/// <summary>
/// <see cref="GetTenantsAnnouncementsQueryHandler"/> 单元测试。
/// </summary>
public sealed class GetTenantsAnnouncementsQueryHandlerTests
{
[Fact]
public async Task GivenQuery_WhenHandle_ThenOrdersAndPaginates()
{
// 1. 准备
var announcements = new List<TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement>
{
AnnouncementTestData.CreateAnnouncement(1, 42, priority: 1, effectiveFrom: DateTime.UtcNow.AddDays(-1)),
AnnouncementTestData.CreateAnnouncement(2, 42, priority: 2, effectiveFrom: DateTime.UtcNow.AddDays(-3)),
AnnouncementTestData.CreateAnnouncement(3, 42, priority: 2, effectiveFrom: DateTime.UtcNow.AddDays(-1)),
AnnouncementTestData.CreateAnnouncement(4, 42, priority: 0, effectiveFrom: DateTime.UtcNow)
};
// 2. (空行后) 模拟数据库端排序:按 priority DESC, effectiveFrom DESC
var sortedAnnouncements = announcements
.OrderByDescending(x => x.Priority)
.ThenByDescending(x => x.EffectiveFrom)
.ToList();
var announcementRepository = new Mock<ITenantAnnouncementRepository>();
announcementRepository
.Setup(x => x.SearchAsync(
It.IsAny<long>(),
It.IsAny<string?>(),
It.IsAny<TakeoutSaaS.Domain.Tenants.Enums.AnnouncementStatus?>(),
It.IsAny<TakeoutSaaS.Domain.Tenants.Enums.TenantAnnouncementType?>(),
It.IsAny<bool?>(),
It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(),
It.IsAny<bool>(),
It.IsAny<int?>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(sortedAnnouncements);
// 3. (空行后) 执行
var handler = new GetTenantsAnnouncementsQueryHandler(announcementRepository.Object);
var query = new GetTenantsAnnouncementsQuery
{
TenantId = 42,
Page = 2,
PageSize = 2
};
var result = await handler.Handle(query, CancellationToken.None);
// 4. (空行后) 断言
announcementRepository.Verify(x => x.SearchAsync(
query.TenantId,
query.Keyword,
query.Status,
query.AnnouncementType,
query.IsActive,
query.EffectiveFrom,
query.EffectiveTo,
null,
true,
12, // estimatedLimit = page * size * 3 = 2 * 2 * 3 = 12
It.IsAny<CancellationToken>()), Times.Once);
result.TotalCount.Should().Be(4);
result.Items.Select(x => x.Id).Should().Equal(1, 4);
result.Page.Should().Be(2);
result.PageSize.Should().Be(2);
}
[Fact]
public async Task GivenOnlyEffective_WhenHandle_ThenFiltersScheduledPublish()
{
// 1. 准备
var announcement1 = AnnouncementTestData.CreateAnnouncement(1, 42, priority: 1, effectiveFrom: DateTime.UtcNow.AddDays(-1));
announcement1.ScheduledPublishAt = DateTime.UtcNow.AddMinutes(-10);
var announcement2 = AnnouncementTestData.CreateAnnouncement(2, 42, priority: 1, effectiveFrom: DateTime.UtcNow.AddDays(-1));
announcement2.ScheduledPublishAt = DateTime.UtcNow.AddMinutes(30);
var announcements = new List<TakeoutSaaS.Domain.Tenants.Entities.TenantAnnouncement>
{
announcement1,
announcement2
};
var announcementRepository = new Mock<ITenantAnnouncementRepository>();
announcementRepository
.Setup(x => x.SearchAsync(
It.IsAny<long>(),
It.IsAny<string?>(),
It.IsAny<TakeoutSaaS.Domain.Tenants.Enums.AnnouncementStatus?>(),
It.IsAny<TakeoutSaaS.Domain.Tenants.Enums.TenantAnnouncementType?>(),
It.IsAny<bool?>(),
It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(),
It.IsAny<DateTime?>(),
It.IsAny<bool>(),
It.IsAny<int?>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(announcements);
// 2. (空行后) 执行
var handler = new GetTenantsAnnouncementsQueryHandler(announcementRepository.Object);
var query = new GetTenantsAnnouncementsQuery
{
TenantId = 42,
OnlyEffective = true,
Page = 1,
PageSize = 10
};
var result = await handler.Handle(query, CancellationToken.None);
// 3. (空行后) 断言
result.Items.Should().ContainSingle();
result.Items[0].Id.Should().Be(1);
}
}