diff --git a/Core.Api.Testing/ApiFixture.cs b/Core.Api.Testing/ApiFixture.cs new file mode 100644 index 000000000..2465e7638 --- /dev/null +++ b/Core.Api.Testing/ApiFixture.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Core.Api.Testing +{ + public abstract class ApiFixture: ApiFixture where TStartup : class + { + public override TestContext CreateTestContext() => + new TestContext(GetConfiguration, SetupServices, SetupWebHostBuilder); + } + + public abstract class ApiFixture: IAsyncLifetime + { + protected readonly TestContext Sut; + + protected HttpClient Client => Sut.Client; + + protected TestServer Server => Sut.Server; + + protected abstract string ApiUrl { get; } + + protected virtual Dictionary GetConfiguration(string fixtureName) => new(); + + protected virtual Action? SetupServices => null; + + protected virtual Func? SetupWebHostBuilder => null; + + protected ApiFixture() + { + Environment.SetEnvironmentVariable("SchemaName", GetType().Name.ToLower()); + + Sut = CreateTestContext(); + } + + public virtual TestContext CreateTestContext() => new(GetConfiguration, SetupServices, SetupWebHostBuilder); + + public virtual Task InitializeAsync() => Task.CompletedTask; + + public virtual Task DisposeAsync() => Task.CompletedTask; + + public async Task Get(string path = "", int maxNumberOfRetries = 0, int retryIntervalInMs = 1000, Func>? check = null) + { + HttpResponseMessage queryResponse; + var retryCount = maxNumberOfRetries; + + var doCheck = check ?? (response => new (response.StatusCode == HttpStatusCode.OK)); + do + { + queryResponse = await Client.GetAsync( + $"{ApiUrl}/{path}" + ); + + if (retryCount == 0 || (await doCheck(queryResponse))) + break; + + await Task.Delay(retryIntervalInMs); + retryCount--; + } while (true); + return queryResponse; + } + + public Task Post(string path, object request) + { + return Client.PostAsync( + $"{ApiUrl}/{path}", + request.ToJsonStringContent() + ); + } + + public Task Post(object request) + { + return Post(string.Empty, request); + } + + public Task Put(string path, object? request = null) + { + return Client.PutAsync( + $"{ApiUrl}/{path}", + request != null ? + request.ToJsonStringContent() + : new StringContent(string.Empty) + ); + } + + public Task Put(object request) + { + return Put(string.Empty, request); + } + } +} diff --git a/Core.Api.Testing/Core.Api.Testing.csproj b/Core.Api.Testing/Core.Api.Testing.csproj new file mode 100644 index 000000000..c9692b243 --- /dev/null +++ b/Core.Api.Testing/Core.Api.Testing.csproj @@ -0,0 +1,19 @@ + + + + net5.0 + enable + true + false + + + + + + + + + + + + diff --git a/Core.Testing/ResponseExtensions.cs b/Core.Api.Testing/ResponseExtensions.cs similarity index 94% rename from Core.Testing/ResponseExtensions.cs rename to Core.Api.Testing/ResponseExtensions.cs index 01a4c80d2..59f1bb3a0 100644 --- a/Core.Testing/ResponseExtensions.cs +++ b/Core.Api.Testing/ResponseExtensions.cs @@ -2,7 +2,7 @@ using System.Threading.Tasks; using FluentAssertions; -namespace Core.Testing +namespace Core.Api.Testing { public static class ResponseExtensions { diff --git a/Core.Testing/SerializationExtensions.cs b/Core.Api.Testing/SerializationExtensions.cs similarity index 97% rename from Core.Testing/SerializationExtensions.cs rename to Core.Api.Testing/SerializationExtensions.cs index 9a2d78e81..95c37f3de 100644 --- a/Core.Testing/SerializationExtensions.cs +++ b/Core.Api.Testing/SerializationExtensions.cs @@ -2,7 +2,7 @@ using System.Text; using Newtonsoft.Json; -namespace Core.Testing +namespace Core.Api.Testing { public static class SerializationExtensions { diff --git a/Core.Testing/TestContext.cs b/Core.Api.Testing/TestContext.cs similarity index 51% rename from Core.Testing/TestContext.cs rename to Core.Api.Testing/TestContext.cs index 3dfeffe4f..73ed60635 100644 --- a/Core.Testing/TestContext.cs +++ b/Core.Api.Testing/TestContext.cs @@ -1,20 +1,12 @@ using System; using System.Collections.Generic; using System.Diagnostics; -using System.Linq; using System.Net.Http; -using System.Threading.Tasks; -using Core.Commands; -using Core.Events; -using Core.Events.External; -using Core.Requests; -using MediatR; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; -using Shipments.Api.Tests.Core; -namespace Core.Testing +namespace Core.Api.Testing { public class TestContext: TestContext where TStartup : class @@ -40,11 +32,7 @@ public class TestContext: IDisposable { public HttpClient Client { get; } - private readonly TestServer server; - - private readonly EventsLog eventsLog = new(); - private readonly DummyExternalEventProducer externalEventProducer = new(); - private readonly DummyExternalCommandBus externalCommandBus = new(); + public readonly TestServer Server; private readonly Func> getConfiguration = _ => new Dictionary(); @@ -65,53 +53,24 @@ public TestContext( var configuration = this.getConfiguration(fixtureName); setupWebHostBuilder ??= webHostBuilder => webHostBuilder; - server = new TestServer(setupWebHostBuilder(TestWebHostBuilder.Create(configuration, services => + Server = new TestServer(setupWebHostBuilder(TestWebHostBuilder.Create(configuration, services => { ConfigureTestServices(services); setupServices?.Invoke(services); }))); - Client = server.CreateClient(); - } - - protected void ConfigureTestServices(IServiceCollection services) - { - services.AddSingleton(eventsLog); - services.AddSingleton(typeof(INotificationHandler<>), typeof(EventListener<>)); - services.AddSingleton(externalEventProducer); - services.AddSingleton(externalCommandBus); - services.AddSingleton(); - } - - public IReadOnlyCollection PublishedExternalEventsOfType() where TEvent : IExternalEvent - { - return externalEventProducer.PublishedEvents.OfType().ToList(); + Client = Server.CreateClient(); } - public IReadOnlyCollection PublishedExternalCommandOfType() where TCommand : ICommand + protected virtual void ConfigureTestServices(IServiceCollection services) { - return externalCommandBus.SentCommands.OfType().ToList(); - } - - public async Task PublishInternalEvent(IEvent @event) - { - using (var scope = server.Host.Services.CreateScope()) - { - var eventBus = scope.ServiceProvider.GetRequiredService(); - await eventBus.Publish(@event); - } } public void Dispose() { - server.Dispose(); + Server.Dispose(); Client.Dispose(); } - - public IReadOnlyCollection PublishedInternalEventsOfType() - { - return eventsLog.PublishedEvents.OfType().ToList(); - } } } diff --git a/Core.Api.Testing/TestWebHostBuilder.cs b/Core.Api.Testing/TestWebHostBuilder.cs new file mode 100644 index 000000000..05cacdc98 --- /dev/null +++ b/Core.Api.Testing/TestWebHostBuilder.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Core.Api.Testing +{ + public static class TestWebHostBuilder + { + public static IWebHostBuilder Create(Dictionary configuration, Action? configureServices = null) + { + var projectDir = Directory.GetCurrentDirectory(); + configureServices ??= _ => { }; + + return new WebHostBuilder() + .UseEnvironment("Development") + .UseContentRoot(projectDir) + .UseConfiguration(new ConfigurationBuilder() + .SetBasePath(projectDir) + .AddJsonFile("appsettings.json", true) + .AddInMemoryCollection(configuration) + .Build() + ) + .ConfigureServices(configureServices); + } + } +} diff --git a/Core.Testing/ApiFixture.cs b/Core.Testing/ApiFixture.cs index e9dc4c38a..5cd4a74cb 100644 --- a/Core.Testing/ApiFixture.cs +++ b/Core.Testing/ApiFixture.cs @@ -1,86 +1,61 @@ -using System; using System.Collections.Generic; -using System.Net; -using System.Net.Http; +using System.Linq; using System.Threading.Tasks; +using Core.Api.Testing; +using Core.Commands; using Core.Events; -using Microsoft.AspNetCore.Hosting; +using Core.Events.External; +using Core.Requests; +using MediatR; using Microsoft.Extensions.DependencyInjection; -using Xunit; +using Shipments.Api.Tests.Core; namespace Core.Testing { - public abstract class ApiFixture: ApiFixture where TStartup : class + public abstract class ApiWithEventsFixture: Api.Testing.ApiFixture where TStartup : class { - public override TestContext CreateTestContext() => - new TestContext(GetConfiguration, SetupServices, SetupWebHostBuilder); - } - - public abstract class ApiFixture: IAsyncLifetime - { - protected readonly TestContext Sut; - - private HttpClient Client => Sut.Client; + private readonly EventsLog eventsLog = new(); + private readonly DummyExternalEventProducer externalEventProducer = new(); + private readonly DummyExternalCommandBus externalCommandBus = new(); - protected abstract string ApiUrl { get; } + public override TestContext CreateTestContext() => + new TestContext(GetConfiguration, (services) => + { + SetupServices?.Invoke(services); + services.AddSingleton(eventsLog); + services.AddSingleton(typeof(INotificationHandler<>), typeof(EventListener<>)); + services.AddSingleton(externalEventProducer); + services.AddSingleton(externalCommandBus); + services.AddSingleton(); - protected virtual Dictionary GetConfiguration(string fixtureName) => new(); + }, SetupWebHostBuilder); - protected virtual Action? SetupServices => null; - protected virtual Func? SetupWebHostBuilder => null; - protected ApiFixture() + public IReadOnlyCollection PublishedExternalEventsOfType() where TEvent : IExternalEvent { - Environment.SetEnvironmentVariable("SchemaName", GetType().Name.ToLower()); - - Sut = CreateTestContext(); + return externalEventProducer.PublishedEvents.OfType().ToList(); } - public virtual TestContext CreateTestContext() => new(GetConfiguration, SetupServices, SetupWebHostBuilder); - - public virtual Task InitializeAsync() => Task.CompletedTask; - - public virtual Task DisposeAsync() => Task.CompletedTask; - - public async Task Get(string path = "", int maxNumberOfRetries = 0, int retryIntervalInMs = 1000, Func>? check = null) + public IReadOnlyCollection PublishedExternalCommandOfType() where TCommand : ICommand { - HttpResponseMessage queryResponse; - var retryCount = maxNumberOfRetries; - - var doCheck = check ?? (response => new (response.StatusCode == HttpStatusCode.OK)); - do - { - queryResponse = await Client.GetAsync( - $"{ApiUrl}/{path}" - ); - - if (retryCount == 0 || (await doCheck(queryResponse))) - break; - - await Task.Delay(retryIntervalInMs); - retryCount--; - } while (true); - return queryResponse; + return externalCommandBus.SentCommands.OfType().ToList(); } - public Task Post(string path, object request) + public async Task PublishInternalEvent(IEvent @event) { - return Client.PostAsync( - $"{ApiUrl}/{path}", - request.ToJsonStringContent() - ); + using var scope = Server.Host.Services.CreateScope(); + var eventBus = scope.ServiceProvider.GetRequiredService(); + await eventBus.Publish(@event); } - public Task Post(object request) + public IReadOnlyCollection PublishedInternalEventsOfType() { - return Post(string.Empty, request); + return eventsLog.PublishedEvents.OfType().ToList(); } + } - public IReadOnlyCollection PublishedExternalEventsOfType() where TEvent : IExternalEvent - => Sut.PublishedExternalEventsOfType(); - - public IReadOnlyCollection PublishedInternalEventsOfType() where TEvent : IEvent - => Sut.PublishedInternalEventsOfType(); + public abstract class ApiWithEventsFixture: Api.Testing.ApiFixture + { } } diff --git a/Core.Testing/Core.Testing.csproj b/Core.Testing/Core.Testing.csproj index 01b0c6a02..d130575ab 100644 --- a/Core.Testing/Core.Testing.csproj +++ b/Core.Testing/Core.Testing.csproj @@ -18,6 +18,7 @@ + diff --git a/Core.WebApi/Core.WebApi.csproj b/Core.WebApi/Core.WebApi.csproj index 02269327a..dc254a3d8 100644 --- a/Core.WebApi/Core.WebApi.csproj +++ b/Core.WebApi/Core.WebApi.csproj @@ -6,10 +6,6 @@ true - - - - diff --git a/Core.WebApi/Middlewares/ExceptionHandling/ExceptionHandlingMiddleware.cs b/Core.WebApi/Middlewares/ExceptionHandling/ExceptionHandlingMiddleware.cs index 53b5cb3cf..8d159270a 100644 --- a/Core.WebApi/Middlewares/ExceptionHandling/ExceptionHandlingMiddleware.cs +++ b/Core.WebApi/Middlewares/ExceptionHandling/ExceptionHandlingMiddleware.cs @@ -1,9 +1,10 @@ using System; +using System.Net; using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Newtonsoft.Json; -using Shipments.Api.Exceptions; namespace Core.WebApi.Middlewares.ExceptionHandling { @@ -13,8 +14,10 @@ public class ExceptionHandlingMiddleware private readonly ILogger logger; - public ExceptionHandlingMiddleware(RequestDelegate next, - ILoggerFactory loggerFactory) + public ExceptionHandlingMiddleware( + RequestDelegate next, + ILoggerFactory loggerFactory + ) { this.next = next; logger = loggerFactory.CreateLogger(); @@ -45,4 +48,29 @@ private Task HandleExceptionAsync(HttpContext context, Exception exception) return context.Response.WriteAsync(result); } } + + public class HttpExceptionWrapper + { + public int StatusCode { get; } + + public string Error { get; } + + public HttpExceptionWrapper(int statusCode, string error) + { + StatusCode = statusCode; + Error = error; + } + } + + public static class ExceptionHandlingMiddlewareExtensions + { + public static IApplicationBuilder UseExceptionHandlingMiddleware( + this IApplicationBuilder app, + Func? customMap = null + ) + { + ExceptionToHttpStatusMapper.CustomMap = customMap; + return app.UseMiddleware(); + } + } } diff --git a/Core.WebApi/Middlewares/ExceptionHandling/ExceptionToHttpStatusMapper.cs b/Core.WebApi/Middlewares/ExceptionHandling/ExceptionToHttpStatusMapper.cs index 85ec62d79..159e0d655 100644 --- a/Core.WebApi/Middlewares/ExceptionHandling/ExceptionToHttpStatusMapper.cs +++ b/Core.WebApi/Middlewares/ExceptionHandling/ExceptionToHttpStatusMapper.cs @@ -1,7 +1,6 @@ using System; using System.ComponentModel.DataAnnotations; using System.Net; -using Core.Exceptions; namespace Core.WebApi.Middlewares.ExceptionHandling { @@ -15,15 +14,12 @@ public HttpStatusCodeInfo(HttpStatusCode code, string message) Code = code; Message = message; } - - public static HttpStatusCodeInfo Create(HttpStatusCode code, string message) - { - return new HttpStatusCodeInfo(code, message); - } } public static class ExceptionToHttpStatusMapper { + public static Func? CustomMap { get; set; } + public static HttpStatusCodeInfo Map(Exception exception) { var code = exception switch @@ -33,8 +29,7 @@ public static HttpStatusCodeInfo Map(Exception exception) InvalidOperationException _ => HttpStatusCode.Conflict, ArgumentException _ => HttpStatusCode.BadRequest, ValidationException _ => HttpStatusCode.BadRequest, - AggregateNotFoundException _ => HttpStatusCode.NotFound, - _ => HttpStatusCode.InternalServerError + _ => CustomMap?.Invoke(exception) ?? HttpStatusCode.InternalServerError }; return new HttpStatusCodeInfo(code, exception.Message); diff --git a/Core.WebApi/Middlewares/ExceptionHandling/HttpExceptionWrapper.cs b/Core.WebApi/Middlewares/ExceptionHandling/HttpExceptionWrapper.cs deleted file mode 100644 index 57a6a6d44..000000000 --- a/Core.WebApi/Middlewares/ExceptionHandling/HttpExceptionWrapper.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Shipments.Api.Exceptions -{ - public class HttpExceptionWrapper - { - public int StatusCode { get; } - - public string Error { get; } - - public HttpExceptionWrapper(int statusCode, string error) - { - StatusCode = statusCode; - Error = error; - } - } -} diff --git a/EventSourcing.NetCore.sln b/EventSourcing.NetCore.sln index ba38ea12c..4e0c2399a 100644 --- a/EventSourcing.NetCore.sln +++ b/EventSourcing.NetCore.sln @@ -202,6 +202,8 @@ EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Marten.Integration.Tests", "Marten.Integration.Tests\Marten.Integration.Tests.csproj", "{D9D67A6C-FE95-4864-B8F1-BD2689134590}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Api.Testing", "Core.Api.Testing\Core.Api.Testing.csproj", "{825A40DB-5AB5-4565-AADB-28AC760D0A43}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -456,6 +458,10 @@ Global {D9D67A6C-FE95-4864-B8F1-BD2689134590}.Debug|Any CPU.Build.0 = Debug|Any CPU {D9D67A6C-FE95-4864-B8F1-BD2689134590}.Release|Any CPU.ActiveCfg = Release|Any CPU {D9D67A6C-FE95-4864-B8F1-BD2689134590}.Release|Any CPU.Build.0 = Release|Any CPU + {825A40DB-5AB5-4565-AADB-28AC760D0A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {825A40DB-5AB5-4565-AADB-28AC760D0A43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {825A40DB-5AB5-4565-AADB-28AC760D0A43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {825A40DB-5AB5-4565-AADB-28AC760D0A43}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -539,6 +545,7 @@ Global {CCE3A700-BCB2-4639-B766-ECEB2E804D63} = {0570E45A-2EB6-4C4C-84E4-2C80E1FECEB5} {B32E504C-C17A-419B-A705-6B876EF44854} = {0570E45A-2EB6-4C4C-84E4-2C80E1FECEB5} {D9D67A6C-FE95-4864-B8F1-BD2689134590} = {107B18E3-65C8-4A6C-976D-7EEED6A6D318} + {825A40DB-5AB5-4565-AADB-28AC760D0A43} = {0570E45A-2EB6-4C4C-84E4-2C80E1FECEB5} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {A5F55604-2FF3-43B7-B657-4F18E6E95D3B} diff --git a/Sample/AsyncProjections/SmartHome.Api/Startup.cs b/Sample/AsyncProjections/SmartHome.Api/Startup.cs index db4153fee..5342dde9d 100644 --- a/Sample/AsyncProjections/SmartHome.Api/Startup.cs +++ b/Sample/AsyncProjections/SmartHome.Api/Startup.cs @@ -1,4 +1,8 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.Net; using Core; +using Core.Exceptions; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -40,7 +44,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs b/Sample/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs index 1fe7a3044..524779713 100644 --- a/Sample/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs +++ b/Sample/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs @@ -6,13 +6,14 @@ using Carts.Carts; using Carts.Carts.GettingCartById; using Carts.Carts.InitializingCart; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using Xunit; namespace Carts.Api.Tests.Carts.InitializingCart { - public class InitializeCartFixture: ApiFixture + public class InitializeCartFixture: ApiWithEventsFixture { protected override string ApiUrl => "/api/Carts"; diff --git a/Sample/ECommerce/Carts/Carts.Api/Startup.cs b/Sample/ECommerce/Carts/Carts.Api/Startup.cs index bda17af1b..8c9717143 100644 --- a/Sample/ECommerce/Carts/Carts.Api/Startup.cs +++ b/Sample/ECommerce/Carts/Carts.Api/Startup.cs @@ -1,5 +1,7 @@ +using System.Net; using System.Runtime.CompilerServices; using Core; +using Core.Exceptions; using Core.Streaming.Kafka; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; @@ -47,7 +49,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/ECommerce/Orders/Orders.Api.Tests/Orders/InitializingOrder/InitializeOrderTests.cs b/Sample/ECommerce/Orders/Orders.Api.Tests/Orders/InitializingOrder/InitializeOrderTests.cs index 39810b396..1f21b2545 100644 --- a/Sample/ECommerce/Orders/Orders.Api.Tests/Orders/InitializingOrder/InitializeOrderTests.cs +++ b/Sample/ECommerce/Orders/Orders.Api.Tests/Orders/InitializingOrder/InitializeOrderTests.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using Orders.Api.Requests.Carts; @@ -12,7 +13,7 @@ namespace Orders.Api.Tests.Orders.InitializingOrder { - public class InitializeOrderFixture: ApiFixture + public class InitializeOrderFixture: ApiWithEventsFixture { protected override string ApiUrl => "/api/Orders"; diff --git a/Sample/ECommerce/Orders/Orders.Api/Startup.cs b/Sample/ECommerce/Orders/Orders.Api/Startup.cs index 809374023..0e695203d 100644 --- a/Sample/ECommerce/Orders/Orders.Api/Startup.cs +++ b/Sample/ECommerce/Orders/Orders.Api/Startup.cs @@ -1,4 +1,6 @@ +using System.Net; using Core; +using Core.Exceptions; using Core.Streaming.Kafka; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; @@ -45,7 +47,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/ECommerce/Payments/Payments.Api.Tests/Payments/RequestingPayment/RequestPaymentsTests.cs b/Sample/ECommerce/Payments/Payments.Api.Tests/Payments/RequestingPayment/RequestPaymentsTests.cs index 1eed394e4..66b2a07a0 100644 --- a/Sample/ECommerce/Payments/Payments.Api.Tests/Payments/RequestingPayment/RequestPaymentsTests.cs +++ b/Sample/ECommerce/Payments/Payments.Api.Tests/Payments/RequestingPayment/RequestPaymentsTests.cs @@ -2,6 +2,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using Payments.Api.Requests.Carts; @@ -10,7 +11,7 @@ namespace Payments.Api.Tests.Payments.RequestingPayment { - public class RequestPaymentsTestsFixture: ApiFixture + public class RequestPaymentsTestsFixture: ApiWithEventsFixture { protected override string ApiUrl => "/api/Payments"; diff --git a/Sample/ECommerce/Payments/Payments.Api/Startup.cs b/Sample/ECommerce/Payments/Payments.Api/Startup.cs index 6c85bc0c7..bbaa39107 100644 --- a/Sample/ECommerce/Payments/Payments.Api/Startup.cs +++ b/Sample/ECommerce/Payments/Payments.Api/Startup.cs @@ -1,4 +1,6 @@ +using System.Net; using Core; +using Core.Exceptions; using Core.Streaming.Kafka; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; @@ -45,7 +47,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/ECommerce/Shipments/Shipments.Api.Tests/Packages/SendPackageTests.cs b/Sample/ECommerce/Shipments/Shipments.Api.Tests/Packages/SendPackageTests.cs index 8d760dd35..8e7ba58a7 100644 --- a/Sample/ECommerce/Shipments/Shipments.Api.Tests/Packages/SendPackageTests.cs +++ b/Sample/ECommerce/Shipments/Shipments.Api.Tests/Packages/SendPackageTests.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using Shipments.Packages; @@ -14,7 +15,7 @@ namespace Shipments.Api.Tests.Packages { - public class SendPackageFixture: ApiFixture + public class SendPackageFixture: ApiWithEventsFixture { protected override string ApiUrl => "/api/Shipments"; diff --git a/Sample/ECommerce/Shipments/Shipments.Api/Startup.cs b/Sample/ECommerce/Shipments/Shipments.Api/Startup.cs index d520b09c1..2113fe3b2 100644 --- a/Sample/ECommerce/Shipments/Shipments.Api/Startup.cs +++ b/Sample/ECommerce/Shipments/Shipments.Api/Startup.cs @@ -1,4 +1,6 @@ +using System.Net; using Core; +using Core.Exceptions; using Core.Streaming.Kafka; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; @@ -45,7 +47,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs index 895ed723b..22377782e 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api.Tests/Carts/InitializingCart/InitializeCartTests.cs @@ -5,7 +5,7 @@ using Carts.Api.Requests.Carts; using Carts.Carts; using Carts.Carts.GettingCartById; -using Core.Testing; +using Core.Api.Testing; using FluentAssertions; using Xunit; diff --git a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Startup.cs b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Startup.cs index 27a06c555..c09dec279 100644 --- a/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Startup.cs +++ b/Sample/EventStoreDB/ECommerce/Carts/Carts.Api/Startup.cs @@ -1,6 +1,8 @@ +using System.Net; using System.Runtime.CompilerServices; using Core; using Core.EventStoreDB; +using Core.Exceptions; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -47,7 +49,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs b/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs index 8e4ad2b6f..5857dcdb2 100644 --- a/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs +++ b/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs @@ -2,6 +2,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using MeetingsManagement.Api; @@ -11,7 +12,7 @@ namespace MeetingsManagement.IntegrationTests.Meetings.CreatingMeeting { - public class CreateMeetingFixture: ApiFixture + public class CreateMeetingFixture: ApiWithEventsFixture { protected override string ApiUrl => MeetingsManagementApi.MeetingsUrl; diff --git a/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/SchedulingMeetings/ScheduleMeetingTests.cs b/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/SchedulingMeetings/ScheduleMeetingTests.cs index 6d9cda97f..c09257058 100644 --- a/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/SchedulingMeetings/ScheduleMeetingTests.cs +++ b/Sample/MeetingsManagement/MeetingsManagement.IntegrationTests/Meetings/SchedulingMeetings/ScheduleMeetingTests.cs @@ -2,7 +2,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; -using Core.Testing; +using Core.Api.Testing; using FluentAssertions; using MeetingsManagement.Api; using MeetingsManagement.Meetings.CreatingMeeting; diff --git a/Sample/MeetingsManagement/MeetingsSearch.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs b/Sample/MeetingsManagement/MeetingsSearch.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs index 5b47836b5..6f365e937 100644 --- a/Sample/MeetingsManagement/MeetingsSearch.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs +++ b/Sample/MeetingsManagement/MeetingsSearch.IntegrationTests/Meetings/CreatingMeeting/CreateMeetingTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using MeetingsSearch.Api; @@ -10,7 +11,7 @@ namespace MeetingsSearch.IntegrationTests.Meetings.CreatingMeeting { - public class CreateMeetingFixture: ApiFixture + public class CreateMeetingFixture: ApiWithEventsFixture { protected override string ApiUrl => MeetingsSearchApi.MeetingsUrl; @@ -26,7 +27,7 @@ public override async Task InitializeAsync() ); // send meeting created event to internal event bus - await Sut.PublishInternalEvent(@event); + await PublishInternalEvent(@event); } } diff --git a/Sample/Tickets/Tickets.Api.Tests/Reservations/CreatingTentativeReservation/CreateTentativeReservationTests.cs b/Sample/Tickets/Tickets.Api.Tests/Reservations/CreatingTentativeReservation/CreateTentativeReservationTests.cs index a71990a52..2e26183dc 100644 --- a/Sample/Tickets/Tickets.Api.Tests/Reservations/CreatingTentativeReservation/CreateTentativeReservationTests.cs +++ b/Sample/Tickets/Tickets.Api.Tests/Reservations/CreatingTentativeReservation/CreateTentativeReservationTests.cs @@ -4,6 +4,7 @@ using System.Net; using System.Net.Http; using System.Threading.Tasks; +using Core.Api.Testing; using Core.Testing; using FluentAssertions; using Tickets.Api.Requests; @@ -18,7 +19,7 @@ namespace Tickets.Api.Tests.Reservations.CreatingTentativeReservation { - public class CreateTentativeReservationFixture: ApiFixture + public class CreateTentativeReservationFixture: ApiWithEventsFixture { protected override string ApiUrl => "/api/Reservations"; diff --git a/Sample/Tickets/Tickets.Api/Startup.cs b/Sample/Tickets/Tickets.Api/Startup.cs index 2f3fd2b44..5c32d3f91 100644 --- a/Sample/Tickets/Tickets.Api/Startup.cs +++ b/Sample/Tickets/Tickets.Api/Startup.cs @@ -1,4 +1,6 @@ +using System.Net; using Core; +using Core.Exceptions; using Core.WebApi.Middlewares.ExceptionHandling; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -42,7 +44,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseDeveloperExceptionPage(); } - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)); + app.UseExceptionHandlingMiddleware(exception => exception switch + { + AggregateNotFoundException _ => HttpStatusCode.NotFound, + _ => HttpStatusCode.InternalServerError + }); app.UseRouting(); diff --git a/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProductDetails/GetProductDetailsTests.cs b/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProductDetails/GetProductDetailsTests.cs index 4d629146d..665ced28e 100644 --- a/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProductDetails/GetProductDetailsTests.cs +++ b/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProductDetails/GetProductDetailsTests.cs @@ -1,7 +1,7 @@ using System; using System.Net; using System.Threading.Tasks; -using Core.Testing; +using Core.Api.Testing; using FluentAssertions; using Microsoft.AspNetCore.Hosting; using Warehouse.Products.GettingProductDetails; diff --git a/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProducts/GetProductsTests.cs b/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProducts/GetProductsTests.cs index a6c154b97..32332545e 100644 --- a/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProducts/GetProductsTests.cs +++ b/Sample/Warehouse/Warehouse.Api.Tests/Products/GettingProducts/GetProductsTests.cs @@ -3,7 +3,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; -using Core.Testing; +using Core.Api.Testing; using FluentAssertions; using Microsoft.AspNetCore.Hosting; using Warehouse.Products.GettingProducts; diff --git a/Sample/Warehouse/Warehouse.Api.Tests/Products/RegisteringProduct/RegisterProductTests.cs b/Sample/Warehouse/Warehouse.Api.Tests/Products/RegisteringProduct/RegisterProductTests.cs index beb125560..dc8161fca 100644 --- a/Sample/Warehouse/Warehouse.Api.Tests/Products/RegisteringProduct/RegisterProductTests.cs +++ b/Sample/Warehouse/Warehouse.Api.Tests/Products/RegisteringProduct/RegisterProductTests.cs @@ -1,7 +1,7 @@ using System; using System.Net; using System.Threading.Tasks; -using Core.Testing; +using Core.Api.Testing; using FluentAssertions; using Microsoft.AspNetCore.Hosting; using Warehouse.Products.RegisteringProduct; diff --git a/Sample/Warehouse/Warehouse.Api.Tests/Warehouse.Api.Tests.csproj b/Sample/Warehouse/Warehouse.Api.Tests/Warehouse.Api.Tests.csproj index 9207fcb3b..1eac1dec9 100644 --- a/Sample/Warehouse/Warehouse.Api.Tests/Warehouse.Api.Tests.csproj +++ b/Sample/Warehouse/Warehouse.Api.Tests/Warehouse.Api.Tests.csproj @@ -25,7 +25,7 @@ - + diff --git a/Sample/Warehouse/Warehouse.Api.Tests/WarehouseTestWebHostBuilder.cs b/Sample/Warehouse/Warehouse.Api.Tests/WarehouseTestWebHostBuilder.cs index d4616526b..992a28aea 100644 --- a/Sample/Warehouse/Warehouse.Api.Tests/WarehouseTestWebHostBuilder.cs +++ b/Sample/Warehouse/Warehouse.Api.Tests/WarehouseTestWebHostBuilder.cs @@ -30,7 +30,7 @@ public static IWebHostBuilder Configure(IWebHostBuilder webHostBuilder, string s }) .Configure(app => { - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)) + app.UseExceptionHandlingMiddleware() .UseRouting() .UseEndpoints(endpoints => { endpoints.UseWarehouseEndpoints(); }) .ConfigureWarehouse(); diff --git a/Sample/Warehouse/Warehouse.Api/Program.cs b/Sample/Warehouse/Warehouse.Api/Program.cs index bbd7f59da..f8798a87b 100644 --- a/Sample/Warehouse/Warehouse.Api/Program.cs +++ b/Sample/Warehouse/Warehouse.Api/Program.cs @@ -16,7 +16,7 @@ }) .Configure(app => { - app.UseMiddleware(typeof(ExceptionHandlingMiddleware)) + app.UseExceptionHandlingMiddleware() .UseRouting() .UseEndpoints(endpoints => { diff --git a/Sample/Warehouse/Warehouse.sln b/Sample/Warehouse/Warehouse.sln index 95f16f75c..66cf6431b 100644 --- a/Sample/Warehouse/Warehouse.sln +++ b/Sample/Warehouse/Warehouse.sln @@ -2,10 +2,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{F6A27B3D-4018-4E66-A008-3E1280C8C685}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Testing", "..\..\Core.Testing\Core.Testing.csproj", "{DD7FF547-0FF1-4B10-9248-1E2700BA3770}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "..\..\Core\Core.csproj", "{35632837-CB02-455C-9570-E79E476C1D90}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Warehouse", "Warehouse\Warehouse.csproj", "{00DCEE41-018D-4CCA-99F3-00876BEB7E06}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Warehouse.Api", "Warehouse.Api\Warehouse.Api.csproj", "{46D1830E-55B1-4F36-959F-2ACF936BFC7C}" @@ -14,25 +10,18 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Warehouse.Api.Tests", "Ware EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.WebApi", "..\..\Core.WebApi\Core.WebApi.csproj", "{A7A09EBA-0B66-4402-A063-69B47D43A66D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core.Api.Testing", "..\..\Core.Api.Testing\Core.Api.Testing.csproj", "{49B8A573-5F71-4087-B30D-D72459ABA0E2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution - {DD7FF547-0FF1-4B10-9248-1E2700BA3770} = {F6A27B3D-4018-4E66-A008-3E1280C8C685} - {35632837-CB02-455C-9570-E79E476C1D90} = {F6A27B3D-4018-4E66-A008-3E1280C8C685} {A7A09EBA-0B66-4402-A063-69B47D43A66D} = {F6A27B3D-4018-4E66-A008-3E1280C8C685} + {49B8A573-5F71-4087-B30D-D72459ABA0E2} = {F6A27B3D-4018-4E66-A008-3E1280C8C685} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DD7FF547-0FF1-4B10-9248-1E2700BA3770}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DD7FF547-0FF1-4B10-9248-1E2700BA3770}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DD7FF547-0FF1-4B10-9248-1E2700BA3770}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DD7FF547-0FF1-4B10-9248-1E2700BA3770}.Release|Any CPU.Build.0 = Release|Any CPU - {35632837-CB02-455C-9570-E79E476C1D90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {35632837-CB02-455C-9570-E79E476C1D90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {35632837-CB02-455C-9570-E79E476C1D90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {35632837-CB02-455C-9570-E79E476C1D90}.Release|Any CPU.Build.0 = Release|Any CPU {00DCEE41-018D-4CCA-99F3-00876BEB7E06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {00DCEE41-018D-4CCA-99F3-00876BEB7E06}.Debug|Any CPU.Build.0 = Debug|Any CPU {00DCEE41-018D-4CCA-99F3-00876BEB7E06}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -49,5 +38,9 @@ Global {A7A09EBA-0B66-4402-A063-69B47D43A66D}.Debug|Any CPU.Build.0 = Debug|Any CPU {A7A09EBA-0B66-4402-A063-69B47D43A66D}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7A09EBA-0B66-4402-A063-69B47D43A66D}.Release|Any CPU.Build.0 = Release|Any CPU + {49B8A573-5F71-4087-B30D-D72459ABA0E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49B8A573-5F71-4087-B30D-D72459ABA0E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49B8A573-5F71-4087-B30D-D72459ABA0E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49B8A573-5F71-4087-B30D-D72459ABA0E2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal