using NSubstitute; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Roles.Create; using SIGCM2.Domain.Entities; using SIGCM2.Domain.Exceptions; namespace SIGCM2.Application.Tests.Roles.Create; public class CreateRolCommandHandlerTests { private readonly IRolRepository _repository = Substitute.For(); private readonly CreateRolCommandHandler _handler; private static CreateRolCommand ValidCommand() => new("cajero_senior", "Cajero Senior", "Con más permisos"); public CreateRolCommandHandlerTests() { _handler = new CreateRolCommandHandler(_repository); } [Fact] public async Task Handle_CodigoDuplicado_ThrowsRolAlreadyExistsException() { var now = new DateTime(2026, 4, 15, 10, 0, 0, DateTimeKind.Utc); _repository.GetByCodigoAsync("cajero_senior") .Returns(new Rol(99, "cajero_senior", "Cajero Senior", null, true, now, null)); var ex = await Assert.ThrowsAsync( () => _handler.Handle(ValidCommand())); Assert.Equal("cajero_senior", ex.Codigo); } [Fact] public async Task Handle_CodigoDuplicado_DoesNotCallAddAsync() { var now = new DateTime(2026, 4, 15, 10, 0, 0, DateTimeKind.Utc); _repository.GetByCodigoAsync(Arg.Any()) .Returns(new Rol(1, "cajero_senior", "X", null, true, now, null)); try { await _handler.Handle(ValidCommand()); } catch (RolAlreadyExistsException) { } await _repository.DidNotReceive().AddAsync(Arg.Any(), Arg.Any()); } [Fact] public async Task Handle_Happy_AddsAndReturnsDtoWithId() { _repository.GetByCodigoAsync(Arg.Any()).Returns((Rol?)null); _repository.AddAsync(Arg.Any(), Arg.Any()).Returns(42); var result = await _handler.Handle(ValidCommand()); Assert.Equal(42, result.Id); Assert.Equal("cajero_senior", result.Codigo); Assert.Equal("Cajero Senior", result.Nombre); Assert.Equal("Con más permisos", result.Descripcion); Assert.True(result.Activo); } [Fact] public async Task Handle_Happy_CallsAddAsyncOnce() { _repository.GetByCodigoAsync(Arg.Any()).Returns((Rol?)null); _repository.AddAsync(Arg.Any(), Arg.Any()).Returns(5); await _handler.Handle(ValidCommand()); await _repository.Received(1).AddAsync( Arg.Is(r => r.Codigo == "cajero_senior" && r.Nombre == "Cajero Senior" && r.Activo), Arg.Any()); } [Fact] public async Task Handle_Happy_WithNullDescripcion_PassesNullToRepository() { _repository.GetByCodigoAsync(Arg.Any()).Returns((Rol?)null); _repository.AddAsync(Arg.Any(), Arg.Any()).Returns(1); await _handler.Handle(new CreateRolCommand("nuevo_rol", "Nuevo", null)); await _repository.Received(1).AddAsync( Arg.Is(r => r.Descripcion == null), Arg.Any()); } }