using Xunit; using Moq; using KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Features.RequestMfaSetup; using KArtSell.Modules.IdentityAccess.ManageIdentityAndRoles.Domain; namespace KArtSell.IdentityAccess.UnitTests.ManageIdentityAndRoles; public class RequestMfaSetupHandlerTests { private readonly Mock _sqlMock; private readonly RequestMfaSetupHandler _handler; public RequestMfaSetupHandlerTests() { _sqlMock = new Mock(); _handler = new RequestMfaSetupHandler(_sqlMock.Object); } [Fact] public async Task HandleAsync_ActiveIdentity_TransitionsToRequiresMfaSetup() { var identityId = Guid.NewGuid(); var request = new RequestMfaSetupRequest { IdentityId = identityId }; _sqlMock.Setup(s => s.GetIdentityAsync(identityId, It.IsAny())) .ReturnsAsync((identityId, IdentityState.Active, 1)); _sqlMock.Setup(s => s.UpdateIdentityStateAsync(identityId, IdentityState.RequiresMfaSetup, 1, It.IsAny())) .Returns(Task.CompletedTask); var response = await _handler.HandleAsync(request, CancellationToken.None); Assert.Equal(identityId, response.IdentityId); Assert.Equal(IdentityState.Active, response.PreviousState); Assert.Equal(IdentityState.RequiresMfaSetup, response.NewState); _sqlMock.Verify(s => s.UpdateIdentityStateAsync(identityId, IdentityState.RequiresMfaSetup, 1, It.IsAny()), Times.Once); } [Fact] public async Task HandleAsync_EmptyIdentityId_ThrowsValidationException() { var request = new RequestMfaSetupRequest { IdentityId = Guid.Empty }; await Assert.ThrowsAsync(() => _handler.HandleAsync(request, CancellationToken.None)); } [Fact] public async Task HandleAsync_IdentityNotFound_ThrowsInvalidOperationException() { var identityId = Guid.NewGuid(); var request = new RequestMfaSetupRequest { IdentityId = identityId }; _sqlMock.Setup(s => s.GetIdentityAsync(identityId, It.IsAny())) .ThrowsAsync(new InvalidOperationException("Identity not found")); await Assert.ThrowsAsync(() => _handler.HandleAsync(request, CancellationToken.None)); } [Fact] public async Task HandleAsync_OptimisticConcurrencyViolation_ThrowsInvalidOperationException() { var identityId = Guid.NewGuid(); var request = new RequestMfaSetupRequest { IdentityId = identityId }; _sqlMock.Setup(s => s.GetIdentityAsync(identityId, It.IsAny())) .ReturnsAsync((identityId, IdentityState.Active, 1)); _sqlMock.Setup(s => s.UpdateIdentityStateAsync(identityId, IdentityState.RequiresMfaSetup, 1, It.IsAny())) .ThrowsAsync(new InvalidOperationException("Optimistic concurrency violation: state changed")); await Assert.ThrowsAsync(() => _handler.HandleAsync(request, CancellationToken.None)); } }