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; /// /// 单元测试。 /// public sealed class GetTenantsAnnouncementsQueryHandlerTests { [Fact] public async Task GivenQuery_WhenHandle_ThenOrdersAndPaginates() { // 1. 准备 var announcements = new List { 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(); announcementRepository .Setup(x => x.SearchAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .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()), 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 { announcement1, announcement2 }; var announcementRepository = new Mock(); announcementRepository .Setup(x => x.SearchAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .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); } }