122 lines
4.5 KiB
C#
122 lines
4.5 KiB
C#
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()));
|
|
}
|
|
}
|