/
softailor
/
gridient
Обзор
Документация
Войти
/
softailor
/
gridient
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
backend/Gridient.Infrastructure.Authentication.Local.Tests/Controllers/PasswordControllerTests.cs
332 строки
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.Password.Commands; using Gridient.Infrastructure.Authentication.Local.Features.Password.Queries; using Gridient.Infrastructure.Authentication.Local.Models; using MediatR; using Microsoft.AspNetCore.Mvc; using Moq; using Xunit; namespace Gridient.Infrastructure.Authentication.Local.Tests.Controllers { public class PasswordControllerTests : ControllerTestBase { private readonly Mock<IMediator> _mediatorMock; private readonly PasswordController _controller; public PasswordControllerTests() { _mediatorMock = new Mock<IMediator>(); _controller = new PasswordController(_mediatorMock.Object); } #region RequestResetToken /// <summary> /// Проверяет, что RequestResetToken возвращает Forbid, если админское создание выключено. /// </summary> [Fact] public async Task RequestResetToken_WhenAdminCreationDisabled_ShouldReturnForbid() { SetupControllerContext(_controller, "admin"); var cancellationToken = CancellationToken.None; var request = new PasswordTokenRequest { Login = "user1" }; _mediatorMock .Setup(m => m.Send(It.IsAny<RequestResetTokenQuery>(), cancellationToken)) .ThrowsAsync(new InvalidOperationException("Генерация токенов сброса пароля отключена")); var result = await _controller.RequestResetToken(request, cancellationToken); result.Should().BeOfType<ForbidResult>(); } /// <summary> /// Проверяет, что RequestResetToken возвращает Unauthorized, если отсутствует логин в User. /// </summary> [Fact] public async Task RequestResetToken_WhenNoUserLogin_ShouldReturnUnauthorized() { // Контекст есть, но логина нет (иначе ControllerBase.User будет null и упадем в NRE) SetupControllerContext(_controller, ""); var cancellationToken = CancellationToken.None; var request = new PasswordTokenRequest { Login = "user1" }; var result = await _controller.RequestResetToken(request, cancellationToken); result.Should().BeOfType<UnauthorizedResult>(); } /// <summary> /// Проверяет, что RequestResetToken возвращает BadRequest, если логин пустой. /// </summary> [Fact] public async Task RequestResetToken_WhenRequestLoginEmpty_ShouldReturnBadRequest() { SetupControllerContext(_controller, "admin"); var cancellationToken = CancellationToken.None; var request = new PasswordTokenRequest { Login = " " }; _mediatorMock .Setup(m => m.Send(It.IsAny<RequestResetTokenQuery>(), cancellationToken)) .ThrowsAsync(new ArgumentException("Логин не может быть пустым", "Login")); var result = await _controller.RequestResetToken(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().BeAssignableTo<string>(); ((string)((BadRequestObjectResult)result).Value!).Should().Contain("Логин не может быть пустым"); } /// <summary> /// Проверяет, что RequestResetToken возвращает NotFound, если сервис не выдал токен. /// </summary> [Fact] public async Task RequestResetToken_WhenServiceReturnsNull_ShouldReturnNotFound() { SetupControllerContext(_controller, "admin"); var cancellationToken = CancellationToken.None; var request = new PasswordTokenRequest { Login = "user1" }; _mediatorMock .Setup(m => m.Send(It.IsAny<RequestResetTokenQuery>(), cancellationToken)) .ReturnsAsync((string?)null); var result = await _controller.RequestResetToken(request, cancellationToken); result.Should().BeOfType<NotFoundResult>(); } /// <summary> /// Проверяет, что RequestResetToken возвращает Ok с токеном и вызывает MediatR с правильным запросом. /// </summary> [Fact] public async Task RequestResetToken_WhenSuccess_ShouldReturnOk_AndCallMediatRWithCorrectQuery() { SetupControllerContext(_controller, "admin"); var cancellationToken = CancellationToken.None; var request = new PasswordTokenRequest { Login = "user1" }; _mediatorMock .Setup(m => m.Send(It.IsAny<RequestResetTokenQuery>(), cancellationToken)) .ReturnsAsync("token"); var result = await _controller.RequestResetToken(request, cancellationToken); result.Should().BeOfType<OkObjectResult>(); ((OkObjectResult)result).Value.Should().Be("token"); _mediatorMock.Verify(m => m.Send( It.Is<RequestResetTokenQuery>(q => q.Login == "user1" && q.CurrentUserLogin == "admin" && q.Operation == "password-reset"), cancellationToken), Times.Once); } #endregion #region ResetPassword /// <summary> /// Проверяет, что ResetPassword возвращает BadRequest, если token пустой. /// </summary> [Fact] public async Task ResetPassword_WhenTokenEmpty_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ThrowsAsync(new ArgumentException("Некорректный токен", "Token")); var result = await _controller.ResetPassword(new UpdatePasswordRequest { Token = "", NewPassword = "pass" }, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().BeAssignableTo<string>(); ((string)((BadRequestObjectResult)result).Value!).Should().Contain("Некорректный токен"); } /// <summary> /// Проверяет, что ResetPassword возвращает BadRequest, если новый пароль пустой. /// </summary> [Fact] public async Task ResetPassword_WhenPasswordEmpty_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ThrowsAsync(new ArgumentException("Пароль не может быть пустым", "NewPassword")); var result = await _controller.ResetPassword(new UpdatePasswordRequest { Token = "t", NewPassword = "" }, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().BeAssignableTo<string>(); ((string)((BadRequestObjectResult)result).Value!).Should().Contain("Пароль не может быть пустым"); } /// <summary> /// Проверяет, что ResetPassword возвращает Ok, если сервис вернул Success. /// </summary> [Fact] public async Task ResetPassword_WhenSuccess_ShouldReturnOk() { var cancellationToken = CancellationToken.None; var request = new UpdatePasswordRequest { Token = "t", NewPassword = "p" }; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ReturnsAsync(PasswordResetResult.Success); var result = await _controller.ResetPassword(request, cancellationToken); result.Should().BeOfType<OkObjectResult>(); ((OkObjectResult)result).Value.Should().Be("Пароль обновлён"); } /// <summary> /// Проверяет, что ResetPassword возвращает BadRequest, если сервис вернул TokenNotFound. /// </summary> [Fact] public async Task ResetPassword_WhenTokenNotFound_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = new UpdatePasswordRequest { Token = "t", NewPassword = "p" }; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ReturnsAsync(PasswordResetResult.TokenNotFound); var result = await _controller.ResetPassword(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().Be("Некорректный токен"); } /// <summary> /// Проверяет, что ResetPassword возвращает BadRequest, если сервис вернул TokenExpired. /// </summary> [Fact] public async Task ResetPassword_WhenTokenExpired_ShouldReturnBadRequest() { var cancellationToken = CancellationToken.None; var request = new UpdatePasswordRequest { Token = "t", NewPassword = "p" }; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ReturnsAsync(PasswordResetResult.TokenExpired); var result = await _controller.ResetPassword(request, cancellationToken); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().Be("Срок действия токена истёк"); } /// <summary> /// Проверяет, что ResetPassword возвращает NotFound, если сервис вернул UserNotFound. /// </summary> [Fact] public async Task ResetPassword_WhenUserNotFound_ShouldReturnNotFound() { var cancellationToken = CancellationToken.None; var request = new UpdatePasswordRequest { Token = "t", NewPassword = "p" }; _mediatorMock .Setup(m => m.Send(It.IsAny<ResetPasswordCommand>(), cancellationToken)) .ReturnsAsync(PasswordResetResult.UserNotFound); var result = await _controller.ResetPassword(request, cancellationToken); result.Should().BeOfType<NotFoundResult>(); } #endregion #region ChangeOwnPassword /// <summary> /// Проверяет, что ChangeOwnPassword возвращает BadRequest, если новый пароль пустой/состоит из пробелов. /// </summary> [Fact] public async Task ChangeOwnPassword_WhenPasswordEmpty_ShouldReturnBadRequest() { SetupControllerContext(_controller, "u1"); _mediatorMock .Setup(m => m.Send(It.IsAny<ChangeOwnPasswordCommand>(), It.IsAny<CancellationToken>())) .ThrowsAsync(new ArgumentException("Пароль не может быть пустым", "NewPassword")); var result = await _controller.ChangeOwnPassword(" ", CancellationToken.None); result.Should().BeOfType<BadRequestObjectResult>(); ((BadRequestObjectResult)result).Value.Should().BeAssignableTo<string>(); ((string)((BadRequestObjectResult)result).Value!).Should().Contain("Пароль не может быть пустым"); } /// <summary> /// Проверяет, что ChangeOwnPassword возвращает Unauthorized, если отсутствует логин пользователя. /// </summary> [Fact] public async Task ChangeOwnPassword_WhenNoLogin_ShouldReturnUnauthorized() { SetupControllerContext(_controller, ""); var result = await _controller.ChangeOwnPassword("new", CancellationToken.None); result.Should().BeOfType<UnauthorizedResult>(); } /// <summary> /// Проверяет, что ChangeOwnPassword возвращает NotFound, если сервис не смог сменить пароль (вернул false). /// </summary> [Fact] public async Task ChangeOwnPassword_WhenServiceReturnsFalse_ShouldReturnNotFound() { SetupControllerContext(_controller, "u1"); _mediatorMock .Setup(m => m.Send(It.IsAny<ChangeOwnPasswordCommand>(), It.IsAny<CancellationToken>())) .ReturnsAsync(false); var result = await _controller.ChangeOwnPassword("new", CancellationToken.None); result.Should().BeOfType<NotFoundResult>(); } /// <summary> /// Проверяет, что ChangeOwnPassword возвращает Ok и вызывает MediatR с правильной командой. /// </summary> [Fact] public async Task ChangeOwnPassword_WhenSuccess_ShouldReturnOk_AndCallMediatRWithCorrectCommand() { SetupControllerContext(_controller, "u1"); _mediatorMock .Setup(m => m.Send(It.IsAny<ChangeOwnPasswordCommand>(), It.IsAny<CancellationToken>())) .ReturnsAsync(true); var result = await _controller.ChangeOwnPassword("new", CancellationToken.None); result.Should().BeOfType<OkObjectResult>(); ((OkObjectResult)result).Value.Should().Be("Пароль обновлён"); _mediatorMock.Verify(m => m.Send( It.Is<ChangeOwnPasswordCommand>(c => c.Login == "u1" && c.NewPassword == "new" && c.Operation == "password-change" && c.UserId == "u1"), It.IsAny<CancellationToken>()), Times.Once); } #endregion } }