using System.Text.Json; using FluentAssertions; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using NSubstitute; using Nashel.BuildingBlocks.Application.Exceptions; using Nashel.Host.Infrastructure.Exceptions; using Xunit; namespace Nashel.Host.Tests; public class GlobalExceptionHandlerTests { private readonly ILogger _logger; private readonly GlobalExceptionHandler _handler; public GlobalExceptionHandlerTests() { _logger = Substitute.For>(); _handler = new GlobalExceptionHandler(_logger); } [Fact] public async Task TryHandleAsync_Should_Return404_When_NotFoundException() { // Arrange (Подготовка) var context = new DefaultHttpContext(); context.Response.Body = new MemoryStream(); var exception = new NotFoundException("User", "123"); // Act (Действие) var result = await _handler.TryHandleAsync(context, exception, CancellationToken.None); // Assert (Проверка) result.Should().BeTrue(); context.Response.StatusCode.Should().Be(StatusCodes.Status404NotFound); context.Response.Body.Seek(0, SeekOrigin.Begin); var responseBody = await new StreamReader(context.Response.Body).ReadToEndAsync(); var problemDetails = JsonSerializer.Deserialize(responseBody, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); problemDetails.Should().NotBeNull(); problemDetails!.Title.Should().Be("Ресурс не найден"); problemDetails.Detail.Should().Contain("User"); problemDetails.Detail.Should().Contain("123"); } [Fact] public async Task TryHandleAsync_Should_Return403_When_ForbiddenAccessException() { // Arrange (Подготовка) var context = new DefaultHttpContext(); context.Response.Body = new MemoryStream(); var exception = new ForbiddenAccessException(); // Act (Действие) var result = await _handler.TryHandleAsync(context, exception, CancellationToken.None); // Assert (Проверка) result.Should().BeTrue(); context.Response.StatusCode.Should().Be(StatusCodes.Status403Forbidden); context.Response.Body.Seek(0, SeekOrigin.Begin); var responseBody = await new StreamReader(context.Response.Body).ReadToEndAsync(); var problemDetails = JsonSerializer.Deserialize(responseBody, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); problemDetails!.Title.Should().Be("Доступ запрещен"); } [Fact] public async Task TryHandleAsync_Should_Return500_When_UnhandledException() { // Arrange (Подготовка) var context = new DefaultHttpContext(); context.Response.Body = new MemoryStream(); var exception = new Exception("Unknown error"); // Act (Действие) var result = await _handler.TryHandleAsync(context, exception, CancellationToken.None); // Assert (Проверка) result.Should().BeTrue(); context.Response.StatusCode.Should().Be(StatusCodes.Status500InternalServerError); context.Response.Body.Seek(0, SeekOrigin.Begin); var responseBody = await new StreamReader(context.Response.Body).ReadToEndAsync(); var problemDetails = JsonSerializer.Deserialize(responseBody, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); problemDetails!.Title.Should().Be("Внутренняя ошибка сервера"); problemDetails.Detail.Should().Be("Произошла непредвиденная ошибка на сервере. Пожалуйста, попробуйте позже."); } }