/
softailor
/
gridient
Обзор
Документация
Войти
/
softailor
/
gridient
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
backend/Gridient.Infrastructure.Authentication.Local.Tests/Controllers/UsersControllerTests.cs
305 строк
14 KB
Jenkins
Auto add
18 фев 2026, 10:19
18 фев 2026, 10:19
1e6c4f8
Код
Авторство
О чём код?
using FluentAssertions; using Gridient.Core.Models; using Gridient.Infrastructure.Authentication.Local.Controllers; using Gridient.Infrastructure.Authentication.Local.Features.AuthUsers.Commands; using Gridient.Infrastructure.Authentication.Local.Tests.Helpers.TestDataBuilders; using MediatR; using Microsoft.AspNetCore.Mvc; using Moq; using Xunit; namespace Gridient.Infrastructure.Authentication.Local.Tests.Controllers { public class UsersControllerTests : ControllerTestBase { private readonly Mock<IMediator> _mediatorMock; private readonly UsersController _controller; public UsersControllerTests() { _mediatorMock = new Mock<IMediator>(); _controller = new UsersController(_mediatorMock.Object); SetupControllerContext(_controller, "admin"); } #region CreateUser /// <summary> /// Проверяет, что CreateUser возвращает BadRequest, если административное создание пользователей отключено (EnableAdminCreation=false). /// </summary> [Fact] public async Task CreateUser_WhenAdminCreationDisabled_ShouldReturnBadRequest() { var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), It.IsAny<CancellationToken>())) .ThrowsAsync(new InvalidOperationException("Создание пользователей администратором отключено")); var result = await _controller.CreateUser(request, CancellationToken.None); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().Be("Создание пользователей администратором отключено"); } /// <summary> /// Проверяет, что CreateUser при пустом пароле создает только Core-пользователя и не создает AuthUser. /// </summary> [Fact] public async Task CreateUser_WhenPasswordEmpty_ShouldCreateCoreUserOnly() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: ""); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ReturnsAsync(1); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<OkObjectResult>(); var okResult = (OkObjectResult)result; okResult.Value.Should().NotBeNull(); // Проверяем, что значение содержит userId через рефлексию var valueType = okResult.Value!.GetType(); var userIdProperty = valueType.GetProperty("userId"); userIdProperty.Should().NotBeNull(); userIdProperty!.GetValue(okResult.Value).Should().Be(1); _mediatorMock.Verify(m => m.Send(It.Is<CreateUserCommand>(c => c.NewUser.Login == "u1"), cancellationToken), Times.Once); } /// <summary> /// Проверяет, что CreateUser при наличии пароля создает пользователя и возвращает userId. /// </summary> [Fact] public async Task CreateUser_WhenPasswordProvided_ShouldReturnUserId() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "U1", password: "P1", email: "TEST@EXAMPLE.COM", displayName: "DN"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ReturnsAsync(1); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<OkObjectResult>(); var okResult = (OkObjectResult)result; okResult.Value.Should().NotBeNull(); // Проверяем, что значение содержит userId через рефлексию var valueType = okResult.Value!.GetType(); var userIdProperty = valueType.GetProperty("userId"); userIdProperty.Should().NotBeNull(); userIdProperty!.GetValue(okResult.Value).Should().Be(1); _mediatorMock.Verify(m => m.Send(It.Is<CreateUserCommand>(c => c.NewUser.Login == "U1"), cancellationToken), Times.Once); } /// <summary> /// Проверяет, что CreateUser вызывает MediatR с правильной командой. /// </summary> [Fact] public async Task CreateUser_ShouldCallMediatRWithCorrectCommand() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: ""); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ReturnsAsync(1); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<OkObjectResult>(); _mediatorMock.Verify(m => m.Send( It.Is<CreateUserCommand>(c => c.NewUser.Login == "u1" && c.CurrentUserLogin == "admin" && c.Operation == "create"), cancellationToken), Times.Once); } /// <summary> /// Проверяет, что CreateUser пробрасывает исключение, если авторизация не пройдена (через AuthorizationBehavior). /// </summary> [Fact] public async Task CreateUser_WhenAuthorizationFails_ShouldThrow() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new Gridient.Core.Authorization.Exceptions.ForbiddenOperationException("Access denied")); Func<Task> act = () => _controller.CreateUser(request, cancellationToken); await act.Should().ThrowAsync<Gridient.Core.Authorization.Exceptions.ForbiddenOperationException>() .WithMessage("Access denied"); } /// <summary> /// Проверяет, что при ошибке создания AuthUser выполняется удаление уже созданного Core-пользователя (rollback) и возвращается BadRequest. /// </summary> [Fact] public async Task CreateUser_WhenAuthUserCreationFailsAndCoreUserDeletionSucceeds_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Database error")); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); var badRequest = (BadRequestObjectResult)result; badRequest.Value.Should().Be("Database error"); } /// <summary> /// Проверяет, что при ошибке создания AuthUser и ошибке отката (удаления Core-пользователя) возвращается BadRequest. /// </summary> [Fact] public async Task CreateUser_WhenAuthUserCreationFailsAndCoreUserDeletionFails_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Database error")); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); var badRequest = (BadRequestObjectResult)result; badRequest.Value.Should().Be("Database error"); } /// <summary> /// Проверяет, что CreateUser возвращает BadRequest, если Core-пользователь с таким логином уже существует. /// </summary> [Fact] public async Task CreateUser_WhenCoreUserAlreadyExists_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Пользователь с логином 'u1' уже существует")); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); var badRequest = (BadRequestObjectResult)result; badRequest.Value.Should().Be("Пользователь с логином 'u1' уже существует"); } /// <summary> /// Проверяет, что CreateUser возвращает BadRequest, если AuthUser с таким логином уже существует. /// </summary> [Fact] public async Task CreateUser_WhenAuthUserAlreadyExists_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "U1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Пользователь с логином 'U1' уже существует")); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); var badRequest = (BadRequestObjectResult)result; badRequest.Value.Should().Be("Пользователь с логином 'U1' уже существует"); } /// <summary> /// Проверяет, что CreateUser возвращает BadRequest, если создание Core-пользователя завершилось ошибкой. /// </summary> [Fact] public async Task CreateUser_WhenCoreUserCreationFails_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = CoreUserTestDataBuilder.CreateUserRequest(login: "u1", password: "p1"); _mediatorMock .Setup(m => m.Send(It.IsAny<CreateUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Core user creation failed")); var result = await _controller.CreateUser(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); var badRequest = (BadRequestObjectResult)result; badRequest.Value.Should().Be("Core user creation failed"); } #endregion #region DeleteUser /// <summary> /// Проверяет, что DeleteUser возвращает NotFound, если Core-пользователь по id не найден. /// </summary> [Fact] public async Task DeleteUser_WhenUserNotFound_ShouldReturnNotFound() { var cancellationToken = CancellationToken.None; _mediatorMock .Setup(m => m.Send(It.IsAny<DeleteUserCommand>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Пользователь с Id 1 не найден")); var result = await _controller.DeleteUser(1, cancellationToken); result.Should().BeOfType<NotFoundObjectResult>(); ((NotFoundObjectResult)result).Value.Should().Be("Пользователь с Id 1 не найден"); } /// <summary> /// Проверяет, что DeleteUser при наличии пользователя удаляет Core-пользователя и связанного AuthUser по логину. /// </summary> [Fact] public async Task DeleteUser_WhenUserExists_ShouldDeleteCoreUserAndAuthUser() { var cancellationToken = CancellationToken.None; _mediatorMock .Setup(m => m.Send(It.IsAny<DeleteUserCommand>(), cancellationToken)) .Returns(Task.CompletedTask); var result = await _controller.DeleteUser(1, cancellationToken); result.Should().BeOfType<OkResult>(); _mediatorMock.Verify(m => m.Send( It.Is<DeleteUserCommand>(c => c.UserId == 1 && c.CurrentUserLogin == "admin" && c.Operation == "delete"), cancellationToken), Times.Once); } /// <summary> /// Проверяет, что DeleteUser пробрасывает исключение, если авторизация операции удаления не пройдена (через AuthorizationBehavior). /// </summary> [Fact] public async Task DeleteUser_WhenAuthorizationFails_ShouldThrow() { var cancellationToken = CancellationToken.None; _mediatorMock .Setup(m => m.Send(It.IsAny<DeleteUserCommand>(), cancellationToken)) .ThrowsAsync(new Gridient.Core.Authorization.Exceptions.ForbiddenOperationException("Access denied")); Func<Task> act = () => _controller.DeleteUser(1, cancellationToken); await act.Should().ThrowAsync<Gridient.Core.Authorization.Exceptions.ForbiddenOperationException>() .WithMessage("Access denied"); } #endregion } }