using FluentAssertions; using NSubstitute; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Pricing.ChargeableChars.GetById; using SIGCM2.Domain.Pricing.ChargeableChars; namespace SIGCM2.Application.Tests.Pricing.ChargeableChars; /// /// PRC-001 — GetChargeableCharConfigByIdQueryHandler tests. /// Covers: found → returns DTO, not-found → returns null. /// public class GetChargeableCharConfigByIdHandlerTests { private readonly IChargeableCharConfigRepository _repo = Substitute.For(); private readonly GetChargeableCharConfigByIdQueryHandler _handler; private static readonly DateOnly Today = new(2026, 4, 20); public GetChargeableCharConfigByIdHandlerTests() { _handler = new GetChargeableCharConfigByIdQueryHandler(_repo); } private static ChargeableCharConfig MakeConfig(long id) => ChargeableCharConfig.Rehydrate(id, null, "$", ChargeableCharCategories.Currency, 1.0m, Today, null, true); // ── Found ─────────────────────────────────────────────────────────────────── [Fact] public async Task Handle_Found_ReturnsDto() { _repo.GetByIdAsync(1L, Arg.Any()) .Returns(MakeConfig(1L)); var result = await _handler.Handle(new GetChargeableCharConfigByIdQuery(1L)); result.Should().NotBeNull(); result!.Id.Should().Be(1L); result.Symbol.Should().Be("$"); result.PricePerUnit.Should().Be(1.0m); result.ValidFrom.Should().Be(Today); result.IsActive.Should().BeTrue(); } // ── Not found ─────────────────────────────────────────────────────────────── [Fact] public async Task Handle_NotFound_ReturnsNull() { _repo.GetByIdAsync(99L, Arg.Any()) .Returns((ChargeableCharConfig?)null); var result = await _handler.Handle(new GetChargeableCharConfigByIdQuery(99L)); result.Should().BeNull(); } }