From 443380d1d1cc905b3c980cc2afa1ed3d33b14cd5 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Sat, 18 Apr 2026 20:50:16 -0300 Subject: [PATCH] test(application): GetRubroByIdQueryHandlerTests dedicado (CAT-001) --- .../GetById/GetRubroByIdQueryHandlerTests.cs | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 tests/SIGCM2.Application.Tests/Rubros/GetById/GetRubroByIdQueryHandlerTests.cs diff --git a/tests/SIGCM2.Application.Tests/Rubros/GetById/GetRubroByIdQueryHandlerTests.cs b/tests/SIGCM2.Application.Tests/Rubros/GetById/GetRubroByIdQueryHandlerTests.cs new file mode 100644 index 0000000..d28ae5f --- /dev/null +++ b/tests/SIGCM2.Application.Tests/Rubros/GetById/GetRubroByIdQueryHandlerTests.cs @@ -0,0 +1,167 @@ +using FluentAssertions; +using Microsoft.Extensions.Time.Testing; +using NSubstitute; +using SIGCM2.Application.Abstractions.Persistence; +using SIGCM2.Application.Rubros.GetById; +using SIGCM2.Domain.Entities; +using SIGCM2.Domain.Exceptions; + +namespace SIGCM2.Application.Tests.Rubros.GetById; + +public class GetRubroByIdQueryHandlerTests +{ + private static readonly FakeTimeProvider FakeTime = + new(new DateTimeOffset(2026, 4, 18, 12, 0, 0, TimeSpan.Zero)); + + private readonly IRubroRepository _repo = Substitute.For(); + + private static DateTime UtcNow => FakeTime.GetUtcNow().UtcDateTime; + + private static Rubro MakeRubro( + int id, + int? parentId = null, + bool activo = true, + int? tarifarioBaseId = null, + DateTime? fechaModificacion = null) + => new(id, parentId, $"Rubro{id}", orden: 1, activo, tarifarioBaseId, + fechaCreacion: UtcNow, fechaModificacion); + + // ── Handle_RubroExiste_ActivoPorDefecto_RetornaDto ─────────────────────── + + [Fact] + public async Task Handle_RubroExiste_ActivoPorDefecto_RetornaDto() + { + var rubro = MakeRubro(id: 5, parentId: 2, tarifarioBaseId: 10); + _repo.GetByIdAsync(5, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 5)); + + result.Should().NotBeNull(); + result.Id.Should().Be(5); + result.Nombre.Should().Be("Rubro5"); + result.ParentId.Should().Be(2); + result.Orden.Should().Be(1); + result.Activo.Should().BeTrue(); + result.TarifarioBaseId.Should().Be(10); + result.FechaCreacion.Should().Be(UtcNow); + result.FechaModificacion.Should().BeNull(); + } + + // ── Handle_RubroNoExiste_LanzaRubroNotFoundException ──────────────────── + + [Fact] + public async Task Handle_RubroNoExiste_LanzaRubroNotFoundException() + { + _repo.GetByIdAsync(99, Arg.Any()).Returns((Rubro?)null); + + var handler = new GetRubroByIdQueryHandler(_repo); + var act = () => handler.Handle(new GetRubroByIdQuery(Id: 99)); + + await act.Should().ThrowAsync() + .WithMessage("*99*"); + } + + // ── Handle_RubroNotFoundException_ContienIdCorrecto ───────────────────── + + [Fact] + public async Task Handle_RubroNotFoundException_ContieneIdCorrecto() + { + _repo.GetByIdAsync(42, Arg.Any()).Returns((Rubro?)null); + + var handler = new GetRubroByIdQueryHandler(_repo); + + var ex = await Assert.ThrowsAsync( + () => handler.Handle(new GetRubroByIdQuery(Id: 42))); + + ex.Id.Should().Be(42); + } + + // ── Handle_CancellationToken_SePropagaAlRepo ───────────────────────────── + + [Fact] + public async Task Handle_CancellationToken_SePropagaAlRepo() + { + // The handler signature accepts CancellationToken and forwards it to the repo. + // We verify the repo is called exactly once with the matching id and any token. + _repo.GetByIdAsync(7, Arg.Any()).Returns(MakeRubro(7)); + + var handler = new GetRubroByIdQueryHandler(_repo); + await handler.Handle(new GetRubroByIdQuery(Id: 7)); + + await _repo.Received(1).GetByIdAsync(7, Arg.Any()); + } + + // ── Handle_FechaCreacion_SeSerializaComoInstantUTC ─────────────────────── + + [Fact] + public async Task Handle_FechaCreacion_SeSerializaComoInstantUTC() + { + var expectedUtc = new DateTime(2026, 1, 15, 8, 30, 0, DateTimeKind.Utc); + var rubro = new Rubro(3, null, "RubroUTC", 0, true, null, expectedUtc, null); + _repo.GetByIdAsync(3, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 3)); + + result.FechaCreacion.Should().Be(expectedUtc); + result.FechaCreacion.Kind.Should().Be(DateTimeKind.Utc); + } + + // ── Handle_FechaModificacion_Null_SeRetornaNull ────────────────────────── + + [Fact] + public async Task Handle_FechaModificacion_Null_SeRetornaNull() + { + var rubro = MakeRubro(id: 8, fechaModificacion: null); + _repo.GetByIdAsync(8, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 8)); + + result.FechaModificacion.Should().BeNull(); + } + + // ── Handle_FechaModificacion_ConValor_SeRetornaCorrecto ────────────────── + + [Fact] + public async Task Handle_FechaModificacion_ConValor_SeRetornaCorrecto() + { + var fechaMod = new DateTime(2026, 3, 10, 10, 0, 0, DateTimeKind.Utc); + var rubro = MakeRubro(id: 9, fechaModificacion: fechaMod); + _repo.GetByIdAsync(9, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 9)); + + result.FechaModificacion.Should().Be(fechaMod); + } + + // ── Handle_RubroRaiz_SinParent_RetornaDtoConParentIdNull ───────────────── + + [Fact] + public async Task Handle_RubroRaiz_SinParent_RetornaDtoConParentIdNull() + { + var rubro = MakeRubro(id: 1, parentId: null); + _repo.GetByIdAsync(1, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 1)); + + result.ParentId.Should().BeNull(); + } + + // ── Handle_RubroConTarifarioBaseId_SeRetornaCorrecto ──────────────────── + + [Fact] + public async Task Handle_RubroConTarifarioBaseId_SeRetornaCorrecto() + { + var rubro = MakeRubro(id: 11, tarifarioBaseId: 42); + _repo.GetByIdAsync(11, Arg.Any()).Returns(rubro); + + var handler = new GetRubroByIdQueryHandler(_repo); + var result = await handler.Handle(new GetRubroByIdQuery(Id: 11)); + + result.TarifarioBaseId.Should().Be(42); + } +}