test(adm-009): IngresosBrutos handler tests mirror (Red)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.IngresosBrutos.Create;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.Create;
|
||||
|
||||
public class CreateIngresosBrutosCommandHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly IAuditLogger _audit = Substitute.For<IAuditLogger>();
|
||||
private readonly CreateIngresosBrutosCommandHandler _handler;
|
||||
|
||||
private static CreateIngresosBrutosCommand ValidCommand() => new(
|
||||
Provincia: ProvinciaArgentina.BuenosAires,
|
||||
Descripcion: "IIBB Buenos Aires",
|
||||
Alicuota: 3.5m,
|
||||
VigenciaDesde: new DateOnly(2024, 1, 1));
|
||||
|
||||
public CreateIngresosBrutosCommandHandlerTests()
|
||||
{
|
||||
_handler = new CreateIngresosBrutosCommandHandler(_repo, _audit);
|
||||
_repo.InsertAsync(Arg.Any<IibbEntity>(), Arg.Any<CancellationToken>()).Returns(55);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_ReturnsDtoWithIdFromRepository()
|
||||
{
|
||||
var result = await _handler.Handle(ValidCommand());
|
||||
|
||||
Assert.Equal(55, result.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_DtoContainsCorrectFields()
|
||||
{
|
||||
var result = await _handler.Handle(ValidCommand());
|
||||
|
||||
Assert.Equal(ProvinciaArgentina.BuenosAires, result.Provincia);
|
||||
Assert.Equal(3.5m, result.Alicuota);
|
||||
Assert.True(result.Activo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsAuditWithCreateAction()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _audit.Received(1).LogAsync(
|
||||
action: "ingresos_brutos.create",
|
||||
targetType: "IngresosBrutos",
|
||||
targetId: "55",
|
||||
metadata: Arg.Any<object?>(),
|
||||
ct: Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AuditLoggerThrows_ExceptionBubblesUp()
|
||||
{
|
||||
_audit.LogAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<object?>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromException(new InvalidOperationException("audit fail")));
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => _handler.Handle(ValidCommand()));
|
||||
}
|
||||
|
||||
// ── triangulation: zero alicuota ─────────────────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithZeroAlicuota_ReturnsDtoWithCorrectAlicuota()
|
||||
{
|
||||
var cmd = new CreateIngresosBrutosCommand(
|
||||
Provincia: ProvinciaArgentina.CiudadAutonomaDeBuenosAires,
|
||||
Descripcion: "IIBB CABA",
|
||||
Alicuota: 0m,
|
||||
VigenciaDesde: new DateOnly(2024, 1, 1));
|
||||
|
||||
var result = await _handler.Handle(cmd);
|
||||
|
||||
Assert.Equal(0m, result.Alicuota);
|
||||
Assert.Equal(ProvinciaArgentina.CiudadAutonomaDeBuenosAires, result.Provincia);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.IngresosBrutos.Deactivate;
|
||||
using SIGCM2.Domain.Exceptions;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.Deactivate;
|
||||
|
||||
public class DeactivateIngresosBrutosCommandHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly IAuditLogger _audit = Substitute.For<IAuditLogger>();
|
||||
private readonly DeactivateIngresosBrutosCommandHandler _handler;
|
||||
|
||||
private static IibbEntity MakeEntity(bool activo = true) =>
|
||||
IibbEntity.FromDb(
|
||||
id: 1, provincia: ProvinciaArgentina.BuenosAires, descripcion: "IIBB BA",
|
||||
alicuota: 3m, activo: activo,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: null, predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
public DeactivateIngresosBrutosCommandHandlerTests()
|
||||
{
|
||||
_handler = new DeactivateIngresosBrutosCommandHandler(_repo, _audit);
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity());
|
||||
_repo.SetActivoAsync(Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>()).Returns(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotFound_ThrowsIngresosBrutosNotFoundException()
|
||||
{
|
||||
_repo.GetByIdAsync(99, Arg.Any<CancellationToken>()).Returns((IibbEntity?)null);
|
||||
|
||||
await Assert.ThrowsAsync<IngresosBrutosNotFoundException>(
|
||||
() => _handler.Handle(new DeactivateIngresosBrutosCommand(99)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsSetActivoFalse()
|
||||
{
|
||||
await _handler.Handle(new DeactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _repo.Received(1).SetActivoAsync(1, false, Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsAuditDeactivate()
|
||||
{
|
||||
await _handler.Handle(new DeactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _audit.Received(1).LogAsync(
|
||||
action: "ingresos_brutos.deactivate",
|
||||
targetType: "IngresosBrutos",
|
||||
targetId: "1",
|
||||
metadata: Arg.Any<object?>(),
|
||||
ct: Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlreadyInactive_IsIdempotent_NoAudit()
|
||||
{
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity(activo: false));
|
||||
|
||||
await _handler.Handle(new DeactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _audit.DidNotReceive().LogAsync(
|
||||
Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<object?>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.IngresosBrutos.GetById;
|
||||
using SIGCM2.Domain.Exceptions;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.GetById;
|
||||
|
||||
public class GetIngresosBrutosByIdQueryHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly GetIngresosBrutosByIdQueryHandler _handler;
|
||||
|
||||
private static IibbEntity MakeEntity(int id = 1) =>
|
||||
IibbEntity.FromDb(
|
||||
id: id, provincia: ProvinciaArgentina.Cordoba, descripcion: "IIBB Córdoba",
|
||||
alicuota: 4m, activo: true,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: null, predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
public GetIngresosBrutosByIdQueryHandlerTests()
|
||||
{
|
||||
_handler = new GetIngresosBrutosByIdQueryHandler(_repo);
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_Found_ReturnsDtoWithCorrectId()
|
||||
{
|
||||
var result = await _handler.Handle(new GetIngresosBrutosByIdQuery(1));
|
||||
|
||||
Assert.Equal(1, result.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_Found_ReturnsDtoWithCorrectProvincia()
|
||||
{
|
||||
var result = await _handler.Handle(new GetIngresosBrutosByIdQuery(1));
|
||||
|
||||
Assert.Equal(ProvinciaArgentina.Cordoba, result.Provincia);
|
||||
Assert.Equal(4m, result.Alicuota);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotFound_ThrowsIngresosBrutosNotFoundException()
|
||||
{
|
||||
_repo.GetByIdAsync(99, Arg.Any<CancellationToken>()).Returns((IibbEntity?)null);
|
||||
|
||||
await Assert.ThrowsAsync<IngresosBrutosNotFoundException>(
|
||||
() => _handler.Handle(new GetIngresosBrutosByIdQuery(99)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.IngresosBrutos.GetHistorial;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.GetHistorial;
|
||||
|
||||
public class GetHistorialIngresosBrutosQueryHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly GetHistorialIngresosBrutosQueryHandler _handler;
|
||||
|
||||
public GetHistorialIngresosBrutosQueryHandlerTests()
|
||||
{
|
||||
_handler = new GetHistorialIngresosBrutosQueryHandler(_repo);
|
||||
}
|
||||
|
||||
private static IibbEntity MakeEntity(int id, int? predecesorId, DateOnly desde) =>
|
||||
IibbEntity.FromDb(
|
||||
id: id, provincia: ProvinciaArgentina.BuenosAires,
|
||||
descripcion: "IIBB BA", alicuota: 3m, activo: true,
|
||||
vigenciaDesde: desde,
|
||||
vigenciaHasta: predecesorId.HasValue ? desde.AddYears(1).AddDays(-1) : null,
|
||||
predecesorId: predecesorId,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_ChainOf2_ReturnsListWith2ItemsInOrder()
|
||||
{
|
||||
var chain = new List<IibbEntity>
|
||||
{
|
||||
MakeEntity(1, null, new DateOnly(2023, 1, 1)),
|
||||
MakeEntity(2, 1, new DateOnly(2024, 1, 1)),
|
||||
};
|
||||
_repo.GetHistorialAsync(2, Arg.Any<CancellationToken>()).Returns(chain);
|
||||
|
||||
var result = await _handler.Handle(new GetHistorialIngresosBrutosQuery(2));
|
||||
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Equal(1, result[0].Version);
|
||||
Assert.Equal(2, result[1].Version);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_SingleVersion_Returns1Item()
|
||||
{
|
||||
var chain = new List<IibbEntity>
|
||||
{ MakeEntity(1, null, new DateOnly(2024, 1, 1)) };
|
||||
_repo.GetHistorialAsync(1, Arg.Any<CancellationToken>()).Returns(chain);
|
||||
|
||||
var result = await _handler.Handle(new GetHistorialIngresosBrutosQuery(1));
|
||||
|
||||
Assert.Single(result);
|
||||
Assert.Equal(ProvinciaArgentina.BuenosAires, result[0].Provincia);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Common;
|
||||
using SIGCM2.Application.IngresosBrutos.List;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.List;
|
||||
|
||||
public class ListIngresosBrutosQueryHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly ListIngresosBrutosQueryHandler _handler;
|
||||
|
||||
private static IibbEntity MakeEntity(int id, ProvinciaArgentina prov) =>
|
||||
IibbEntity.FromDb(
|
||||
id: id, provincia: prov, descripcion: "IIBB test",
|
||||
alicuota: 3m, activo: true,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: null, predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
public ListIngresosBrutosQueryHandlerTests()
|
||||
{
|
||||
_handler = new ListIngresosBrutosQueryHandler(_repo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_WithItems_ReturnsPagedResultWithMappedDtos()
|
||||
{
|
||||
var items = new List<IibbEntity>
|
||||
{
|
||||
MakeEntity(1, ProvinciaArgentina.BuenosAires),
|
||||
MakeEntity(2, ProvinciaArgentina.Cordoba),
|
||||
};
|
||||
_repo.ListAsync(Arg.Any<IngresosBrutosQuery>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new PagedResult<IibbEntity>(items, 1, 10, 2));
|
||||
|
||||
var result = await _handler.Handle(new ListIngresosBrutosQuery(1, 10, null, null));
|
||||
|
||||
Assert.Equal(2, result.Items.Count);
|
||||
Assert.Equal(2, result.Total);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_PassesProvinciaFilterToRepository()
|
||||
{
|
||||
_repo.ListAsync(Arg.Any<IngresosBrutosQuery>(), Arg.Any<CancellationToken>())
|
||||
.Returns(new PagedResult<IibbEntity>(new List<IibbEntity>(), 1, 10, 0));
|
||||
|
||||
await _handler.Handle(new ListIngresosBrutosQuery(1, 10, true, ProvinciaArgentina.Cordoba));
|
||||
|
||||
await _repo.Received(1).ListAsync(
|
||||
Arg.Is<IngresosBrutosQuery>(q => q.Provincia == ProvinciaArgentina.Cordoba && q.Activo == true),
|
||||
Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.IngresosBrutos.NuevaVersion;
|
||||
using SIGCM2.Domain.Exceptions;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.NuevaVersion;
|
||||
|
||||
public class NuevaVersionIngresosBrutosCommandHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly IAuditLogger _audit = Substitute.For<IAuditLogger>();
|
||||
private readonly NuevaVersionIngresosBrutosCommandHandler _handler;
|
||||
|
||||
private static IibbEntity MakePredecesora(int id = 1, DateOnly? vigenciaHasta = null) =>
|
||||
IibbEntity.FromDb(
|
||||
id: id, provincia: ProvinciaArgentina.BuenosAires, descripcion: "IIBB BA",
|
||||
alicuota: 3m, activo: true,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: vigenciaHasta,
|
||||
predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow,
|
||||
fechaModificacion: null);
|
||||
|
||||
private static NuevaVersionIngresosBrutosCommand ValidCommand() => new(
|
||||
PredecesoraId: 1,
|
||||
NuevaAlicuota: 5m,
|
||||
VigenciaDesde: new DateOnly(2025, 1, 1));
|
||||
|
||||
public NuevaVersionIngresosBrutosCommandHandlerTests()
|
||||
{
|
||||
_handler = new NuevaVersionIngresosBrutosCommandHandler(_repo, _audit);
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakePredecesora());
|
||||
_repo.UpdateCierreVigenciaAsync(Arg.Any<int>(), Arg.Any<DateOnly>(), Arg.Any<CancellationToken>()).Returns(true);
|
||||
_repo.InsertAsync(Arg.Any<IibbEntity>(), Arg.Any<CancellationToken>()).Returns(88);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_ReturnsDtoWithCorrectIds()
|
||||
{
|
||||
var result = await _handler.Handle(ValidCommand());
|
||||
|
||||
Assert.Equal(1, result.PredecesoraId);
|
||||
Assert.Equal(88, result.NuevaVersionId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsUpdateCierreVigenciaOnce()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _repo.Received(1).UpdateCierreVigenciaAsync(
|
||||
1, new DateOnly(2024, 12, 31), Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsInsertWithCorrectAlicuota()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _repo.Received(1).InsertAsync(
|
||||
Arg.Is<IibbEntity>(e => e.Alicuota == 5m && e.PredecesorId == 1),
|
||||
Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsAuditOnceWithCorrectAction()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _audit.Received(1).LogAsync(
|
||||
action: "ingresos_brutos.nueva_version",
|
||||
targetType: "IngresosBrutos",
|
||||
targetId: Arg.Any<string>(),
|
||||
metadata: Arg.Any<object?>(),
|
||||
ct: Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_PredecesoraNotFound_ThrowsIngresosBrutosNotFoundException()
|
||||
{
|
||||
_repo.GetByIdAsync(999, Arg.Any<CancellationToken>())
|
||||
.Returns((IibbEntity?)null);
|
||||
|
||||
await Assert.ThrowsAsync<IngresosBrutosNotFoundException>(
|
||||
() => _handler.Handle(new NuevaVersionIngresosBrutosCommand(999, 5m, new DateOnly(2025, 1, 1))));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_PredecesoraYaCerrada_ThrowsPredecesorYaCerradoException()
|
||||
{
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>())
|
||||
.Returns(MakePredecesora(vigenciaHasta: new DateOnly(2024, 12, 31)));
|
||||
|
||||
await Assert.ThrowsAsync<PredecesorYaCerradoException>(
|
||||
() => _handler.Handle(ValidCommand()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_UpdateCierreVigenciaReturnsFalse_ThrowsPredecesorYaCerradoException()
|
||||
{
|
||||
_repo.UpdateCierreVigenciaAsync(Arg.Any<int>(), Arg.Any<DateOnly>(), Arg.Any<CancellationToken>())
|
||||
.Returns(false);
|
||||
|
||||
await Assert.ThrowsAsync<PredecesorYaCerradoException>(
|
||||
() => _handler.Handle(ValidCommand()));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AuditLoggerThrows_ExceptionBubblesUp()
|
||||
{
|
||||
_audit.LogAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<object?>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromException(new InvalidOperationException("audit fail")));
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => _handler.Handle(ValidCommand()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.IngresosBrutos.Reactivate;
|
||||
using SIGCM2.Domain.Exceptions;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.Reactivate;
|
||||
|
||||
public class ReactivateIngresosBrutosCommandHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly IAuditLogger _audit = Substitute.For<IAuditLogger>();
|
||||
private readonly ReactivateIngresosBrutosCommandHandler _handler;
|
||||
|
||||
private static IibbEntity MakeEntity(bool activo = false) =>
|
||||
IibbEntity.FromDb(
|
||||
id: 1, provincia: ProvinciaArgentina.BuenosAires, descripcion: "IIBB BA",
|
||||
alicuota: 3m, activo: activo,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: null, predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
public ReactivateIngresosBrutosCommandHandlerTests()
|
||||
{
|
||||
_handler = new ReactivateIngresosBrutosCommandHandler(_repo, _audit);
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity());
|
||||
_repo.SetActivoAsync(Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>()).Returns(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotFound_ThrowsIngresosBrutosNotFoundException()
|
||||
{
|
||||
_repo.GetByIdAsync(99, Arg.Any<CancellationToken>()).Returns((IibbEntity?)null);
|
||||
|
||||
await Assert.ThrowsAsync<IngresosBrutosNotFoundException>(
|
||||
() => _handler.Handle(new ReactivateIngresosBrutosCommand(99)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsSetActivoTrue()
|
||||
{
|
||||
await _handler.Handle(new ReactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _repo.Received(1).SetActivoAsync(1, true, Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsAuditReactivate()
|
||||
{
|
||||
await _handler.Handle(new ReactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _audit.Received(1).LogAsync(
|
||||
action: "ingresos_brutos.reactivate",
|
||||
targetType: "IngresosBrutos",
|
||||
targetId: "1",
|
||||
metadata: Arg.Any<object?>(),
|
||||
ct: Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AlreadyActive_IsIdempotent_NoAudit()
|
||||
{
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity(activo: true));
|
||||
|
||||
await _handler.Handle(new ReactivateIngresosBrutosCommand(1));
|
||||
|
||||
await _audit.DidNotReceive().LogAsync(
|
||||
Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<object?>(), Arg.Any<CancellationToken>());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
using NSubstitute;
|
||||
using SIGCM2.Application.Abstractions.Persistence;
|
||||
using SIGCM2.Application.Audit;
|
||||
using SIGCM2.Application.IngresosBrutos.Update;
|
||||
using SIGCM2.Domain.Exceptions;
|
||||
using SIGCM2.Domain.Fiscal;
|
||||
using IibbEntity = SIGCM2.Domain.Entities.IngresosBrutos;
|
||||
|
||||
namespace SIGCM2.Application.Tests.IngresosBrutos.Update;
|
||||
|
||||
public class UpdateIngresosBrutosCommandHandlerTests
|
||||
{
|
||||
private readonly IIngresosBrutosRepository _repo = Substitute.For<IIngresosBrutosRepository>();
|
||||
private readonly IAuditLogger _audit = Substitute.For<IAuditLogger>();
|
||||
private readonly UpdateIngresosBrutosCommandHandler _handler;
|
||||
|
||||
private static IibbEntity MakeEntity(int id = 1) =>
|
||||
IibbEntity.FromDb(
|
||||
id: id, provincia: ProvinciaArgentina.BuenosAires, descripcion: "IIBB BA",
|
||||
alicuota: 3m, activo: true,
|
||||
vigenciaDesde: new DateOnly(2024, 1, 1),
|
||||
vigenciaHasta: null, predecesorId: null,
|
||||
fechaCreacion: DateTime.UtcNow, fechaModificacion: null);
|
||||
|
||||
private static UpdateIngresosBrutosCommand ValidCommand(int id = 1) => new(
|
||||
Id: id, Descripcion: "IIBB BA actualizado", Activo: true);
|
||||
|
||||
public UpdateIngresosBrutosCommandHandlerTests()
|
||||
{
|
||||
_handler = new UpdateIngresosBrutosCommandHandler(_repo, _audit);
|
||||
_repo.GetByIdAsync(1, Arg.Any<CancellationToken>()).Returns(MakeEntity());
|
||||
_repo.UpdateCosmeticoAsync(Arg.Any<int>(), Arg.Any<string>(), Arg.Any<bool>(),
|
||||
Arg.Any<CancellationToken>()).Returns(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_NotFound_ThrowsIngresosBrutosNotFoundException()
|
||||
{
|
||||
_repo.GetByIdAsync(99, Arg.Any<CancellationToken>()).Returns((IibbEntity?)null);
|
||||
|
||||
await Assert.ThrowsAsync<IngresosBrutosNotFoundException>(
|
||||
() => _handler.Handle(ValidCommand(99)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_ReturnsDtoWithUpdatedDescription()
|
||||
{
|
||||
var result = await _handler.Handle(ValidCommand());
|
||||
|
||||
Assert.Equal("IIBB BA actualizado", result.Descripcion);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsUpdateCosmeticoOnce()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _repo.Received(1).UpdateCosmeticoAsync(
|
||||
1, "IIBB BA actualizado", true, Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_HappyPath_CallsAuditWithUpdateAction()
|
||||
{
|
||||
await _handler.Handle(ValidCommand());
|
||||
|
||||
await _audit.Received(1).LogAsync(
|
||||
action: "ingresos_brutos.update",
|
||||
targetType: "IngresosBrutos",
|
||||
targetId: "1",
|
||||
metadata: Arg.Any<object?>(),
|
||||
ct: Arg.Any<CancellationToken>());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Handle_AuditLoggerThrows_ExceptionBubblesUp()
|
||||
{
|
||||
_audit.LogAsync(Arg.Any<string>(), Arg.Any<string>(), Arg.Any<string>(),
|
||||
Arg.Any<object?>(), Arg.Any<CancellationToken>())
|
||||
.Returns(Task.FromException(new InvalidOperationException("audit fail")));
|
||||
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(
|
||||
() => _handler.Handle(ValidCommand()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user