From 239db37da085f31bc48f512d2b7697172670b93d Mon Sep 17 00:00:00 2001 From: Franklin Bitencourt Dantas Date: Mon, 20 May 2024 11:34:12 -0300 Subject: [PATCH] Adds Exception Middleware * Adds ExceptionMiddleware * Adds Exception Middleware unit tests --- .../IServiceCollectionExtensions.cs | 9 +- .../Middlewares/ExceptionMiddleware.cs} | 26 ++++-- .../core/FinancialHub.Core.WebApi/Startup.cs | 31 ++++--- .../Middlewares/ExceptionMiddlewareTests.cs | 84 +++++++++++++++++++ 4 files changed, 118 insertions(+), 32 deletions(-) rename src/api/core/{FinancialHub.Core.Infra.Logs/Middlewares/LogMiddleware.cs => FinancialHub.Core.WebApi/Middlewares/ExceptionMiddleware.cs} (59%) create mode 100644 tests/core/FinancialHub.Core.WebApi.Tests/Middlewares/ExceptionMiddlewareTests.cs diff --git a/src/api/core/FinancialHub.Core.Infra.Logs/Extensions/Configurations/IServiceCollectionExtensions.cs b/src/api/core/FinancialHub.Core.Infra.Logs/Extensions/Configurations/IServiceCollectionExtensions.cs index 1ce043aa..9e1fcbd0 100644 --- a/src/api/core/FinancialHub.Core.Infra.Logs/Extensions/Configurations/IServiceCollectionExtensions.cs +++ b/src/api/core/FinancialHub.Core.Infra.Logs/Extensions/Configurations/IServiceCollectionExtensions.cs @@ -1,6 +1,4 @@ -using FinancialHub.Core.Infra.Logs.Middlewares; -using Microsoft.AspNetCore.Builder; -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; namespace FinancialHub.Core.Infra.Logs.Extensions.Configurations { @@ -11,10 +9,5 @@ public static IServiceCollection AddCoreLogging(this IServiceCollection services services.AddLogging(); return services; } - - public static IApplicationBuilder UseLogRequest(this IApplicationBuilder builder) - { - return builder.UseMiddleware(); - } } } diff --git a/src/api/core/FinancialHub.Core.Infra.Logs/Middlewares/LogMiddleware.cs b/src/api/core/FinancialHub.Core.WebApi/Middlewares/ExceptionMiddleware.cs similarity index 59% rename from src/api/core/FinancialHub.Core.Infra.Logs/Middlewares/LogMiddleware.cs rename to src/api/core/FinancialHub.Core.WebApi/Middlewares/ExceptionMiddleware.cs index 27ba1339..bc77b708 100644 --- a/src/api/core/FinancialHub.Core.Infra.Logs/Middlewares/LogMiddleware.cs +++ b/src/api/core/FinancialHub.Core.WebApi/Middlewares/ExceptionMiddleware.cs @@ -1,14 +1,14 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; -namespace FinancialHub.Core.Infra.Logs.Middlewares +namespace FinancialHub.Core.WebApi.Middlewares { - public class LogMiddleware + public class ExceptionMiddleware { private readonly RequestDelegate next; - private readonly ILogger logger; + private readonly ILogger logger; - public LogMiddleware(RequestDelegate next, ILogger logger) + public ExceptionMiddleware(RequestDelegate next, ILogger logger) { this.next = next; this.logger = logger; @@ -25,13 +25,23 @@ public async Task InvokeAsync(HttpContext context) } catch (Exception exception) { - var status = context.Response.StatusCode; this.logger.LogError( exception, - "[{request}] - {path} error with message {message} and status {status}", - method, path, exception.Message, status + "[{request}] - {path} error with message {message}", + method, path, exception.Message + ); + context.Response.StatusCode = 500; + await context.Response.WriteAsJsonAsync( + new + { + HasError = true, + Error = new + { + Code = 500, + exception.Message, + } + } ); - throw; } finally { diff --git a/src/api/core/FinancialHub.Core.WebApi/Startup.cs b/src/api/core/FinancialHub.Core.WebApi/Startup.cs index d0b4ddad..0a39f25a 100644 --- a/src/api/core/FinancialHub.Core.WebApi/Startup.cs +++ b/src/api/core/FinancialHub.Core.WebApi/Startup.cs @@ -9,6 +9,7 @@ using FinancialHub.Core.Resources.Extensions; using FinancialHub.Core.Infra.Data.Extensions.Configurations; using FinancialHub.Core.Infra.Logs.Extensions.Configurations; +using FinancialHub.Core.WebApi.Middlewares; namespace FinancialHub.Core.WebApi { @@ -23,21 +24,19 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { - services.AddApiConfigurations(); - services.AddApiDocs(); - services.AddApiLogging(); - - services.AddHttpLogging(logging => - { - logging.LoggingFields = Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.All; - }); - - services.AddCoreResources(); - services.AddCoreServices(); - services.AddCoreInfra(); - services.AddRepositories(Configuration); - - services.AddMvc().AddNewtonsoftJson(); + services + .AddApiConfigurations() + .AddApiDocs() + .AddApiLogging(); + + services.AddCoreResources() + .AddCoreServices() + .AddCoreInfra() + .AddRepositories(Configuration); + + services + .AddMvc() + .AddNewtonsoftJson(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -50,7 +49,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) } app.UseRouting(); - app.UseLogRequest(); + app.UseMiddleware(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); diff --git a/tests/core/FinancialHub.Core.WebApi.Tests/Middlewares/ExceptionMiddlewareTests.cs b/tests/core/FinancialHub.Core.WebApi.Tests/Middlewares/ExceptionMiddlewareTests.cs new file mode 100644 index 00000000..c82e2579 --- /dev/null +++ b/tests/core/FinancialHub.Core.WebApi.Tests/Middlewares/ExceptionMiddlewareTests.cs @@ -0,0 +1,84 @@ +using FinancialHub.Core.WebApi.Middlewares; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using System.IO; +using System.Text.Json; + +namespace FinancialHub.Core.WebApi.Tests.Middleware +{ + public class ExceptionMiddlewareTests + { + private ILogger logger; + + [SetUp] + public void Setup() + { + this.logger = new Mock>().Object; + } + + [Test] + public void InvokeAsync_SuccessRequest_ShouldNotThrowException() + { + static Task next(HttpContext hc) => Task.CompletedTask; + var middleware = new ExceptionMiddleware(next, this.logger); + var context = new DefaultHttpContext(); + + Assert.That( + async () => await middleware.InvokeAsync(context), + Throws.Nothing + ); + } + + [Test] + public async Task InvokeAsync_SuccessRequest_ShouldNotChangePayload() + { + static Task next(HttpContext hc) => Task.CompletedTask; + + var middleware = new ExceptionMiddleware(next, this.logger); + + var response = new Mock(); + response + .SetupGet(x => x.StatusCode) + .Returns(200); + var context = new Mock(); + context + .SetupGet(x => x.Response) + .Returns(response.Object); + context + .SetupGet(x => x.Request) + .Returns(new DefaultHttpContext().Request); + + var defaultContext = new DefaultHttpContext(); + + await middleware.InvokeAsync(context.Object); + + Assert.That(response.Object.StatusCode, Is.EqualTo(200)); + } + + [Test] + public void InvokeAsync_RequestWithUnhandledError_ShouldNotThrowException() + { + static Task next(HttpContext hc) => Task.CompletedTask; + var middleware = new ExceptionMiddleware(next, this.logger); + var context = new DefaultHttpContext(); + + Assert.That( + async () => await middleware.InvokeAsync(context), + Throws.Nothing + ); + } + + [Test] + public async Task InvokeAsync_RequestWithUnhandledError_ShouldChangeStatusTo500() + { + static Task next(HttpContext hc) => Task.FromException(new Exception("Error")); + + var middleware = new ExceptionMiddleware(next, this.logger); + var context = new DefaultHttpContext(); + + await middleware.InvokeAsync(context); + + Assert.That(context.Response.StatusCode, Is.EqualTo(500)); + } + } +}