From 0bdda4eff394c580b7f7a8713111e0799d0e2d8e Mon Sep 17 00:00:00 2001 From: dudu Date: Wed, 8 Feb 2023 07:19:59 +0800 Subject: [PATCH] add a test case for IntegrationEventHandler --- .editorconfig | 3 + ...Architecture.IntegrationTestProject.csproj | 18 +++--- .../Constants.cs | 7 +++ .../TestIntegrationEventHandler.cs | 30 ++++++++++ .../Program.cs | 11 ++-- ...blogs.Architecture.IntegrationTests.csproj | 6 +- .../DaprTests.cs | 3 +- .../DddWebTestCollection.cs | 7 --- .../IntegrationEventHandlerTests.cs | 55 +++++++++++++++++++ .../IntegrationTestCollection.cs | 7 +++ ...stFactory.cs => IntegrationTestFactory.cs} | 2 +- .../IntegrationTestFramework.cs | 19 +++++++ .../Subscription.cs | 22 ++++++++ .../TestIntegrationEvent.cs | 2 +- 14 files changed, 167 insertions(+), 25 deletions(-) create mode 100644 test/Cnblogs.Architecture.IntegrationTestProject/Constants.cs create mode 100644 test/Cnblogs.Architecture.IntegrationTestProject/EventHandlers/TestIntegrationEventHandler.cs delete mode 100644 test/Cnblogs.Architecture.IntegrationTests/DddWebTestCollection.cs create mode 100644 test/Cnblogs.Architecture.IntegrationTests/IntegrationEventHandlerTests.cs create mode 100644 test/Cnblogs.Architecture.IntegrationTests/IntegrationTestCollection.cs rename test/Cnblogs.Architecture.IntegrationTests/{DddWebTestFactory.cs => IntegrationTestFactory.cs} (68%) create mode 100644 test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFramework.cs create mode 100644 test/Cnblogs.Architecture.IntegrationTests/Subscription.cs diff --git a/.editorconfig b/.editorconfig index 563f844..b4c14cd 100644 --- a/.editorconfig +++ b/.editorconfig @@ -79,6 +79,9 @@ indent_style = space indent_size = 4 tab_width = 4 +[*.xml] +indent_size = 2 + #### C# Coding Conventions #### [*.cs] diff --git a/test/Cnblogs.Architecture.IntegrationTestProject/Cnblogs.Architecture.IntegrationTestProject.csproj b/test/Cnblogs.Architecture.IntegrationTestProject/Cnblogs.Architecture.IntegrationTestProject.csproj index 1610ac2..9c5f369 100644 --- a/test/Cnblogs.Architecture.IntegrationTestProject/Cnblogs.Architecture.IntegrationTestProject.csproj +++ b/test/Cnblogs.Architecture.IntegrationTestProject/Cnblogs.Architecture.IntegrationTestProject.csproj @@ -1,13 +1,13 @@ - + - - - + + + - - - - - + + + + + diff --git a/test/Cnblogs.Architecture.IntegrationTestProject/Constants.cs b/test/Cnblogs.Architecture.IntegrationTestProject/Constants.cs new file mode 100644 index 0000000..96717c4 --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTestProject/Constants.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.Architecture.IntegrationTestProject; + +public static class Constants +{ + public const string AppName = "test-web"; + public const string IntegrationEventIdHeaderName = "X-IntegrationEvent-Id"; +} diff --git a/test/Cnblogs.Architecture.IntegrationTestProject/EventHandlers/TestIntegrationEventHandler.cs b/test/Cnblogs.Architecture.IntegrationTestProject/EventHandlers/TestIntegrationEventHandler.cs new file mode 100644 index 0000000..1b919cb --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTestProject/EventHandlers/TestIntegrationEventHandler.cs @@ -0,0 +1,30 @@ +using Cnblogs.Architecture.Ddd.EventBus.Abstractions; +using Cnblogs.Architecture.TestIntegrationEvents; +using MediatR; +using System.Diagnostics; + +namespace Cnblogs.Architecture.IntegrationTestProject.EventHandlers; + +public class TestIntegrationEventHandler : IIntegrationEventHandler +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public TestIntegrationEventHandler(IHttpContextAccessor httpContextAccessor) + { + _httpContextAccessor = httpContextAccessor; + } + + public Task Handle(TestIntegrationEvent notification, CancellationToken cancellationToken) + { + var context = _httpContextAccessor.HttpContext; + context?.Response.OnStarting(() => + { + context.Response.Headers.Add(Constants.IntegrationEventIdHeaderName, notification.Id.ToString()); + return Task.CompletedTask; + }); + + Debug.WriteLine($"notification message: " + notification.Message); + + return Task.CompletedTask; + } +} diff --git a/test/Cnblogs.Architecture.IntegrationTestProject/Program.cs b/test/Cnblogs.Architecture.IntegrationTestProject/Program.cs index bd06489..ba8f983 100644 --- a/test/Cnblogs.Architecture.IntegrationTestProject/Program.cs +++ b/test/Cnblogs.Architecture.IntegrationTestProject/Program.cs @@ -1,22 +1,25 @@ +using System.Reflection; using Cnblogs.Architecture.Ddd.Cqrs.AspNetCore; using Cnblogs.Architecture.Ddd.Cqrs.DependencyInjection.EventBus.Dapr; +using Cnblogs.Architecture.IntegrationTestProject; using Cnblogs.Architecture.IntegrationTestProject.Application.Commands; using Cnblogs.Architecture.IntegrationTestProject.Application.Queries; using Cnblogs.Architecture.IntegrationTestProject.Payloads; using Cnblogs.Architecture.TestIntegrationEvents; -const string appName = "test-web"; - var builder = WebApplication.CreateBuilder(args); -builder.Services.AddCqrs(typeof(Cnblogs.Architecture.IntegrationTestProject.Program).Assembly) +builder.Services.AddCqrs( + Assembly.GetExecutingAssembly(), + typeof(TestIntegrationEvent).Assembly) .AddDefaultDateTimeAndRandomProvider(); -builder.Services.AddDaprEventBus(appName); +builder.Services.AddDaprEventBus(Constants.AppName); builder.Services.AddControllers().AddCqrsModelBinderProvider(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddCnblogsApiVersioning(); builder.Services.AddSwaggerGen(); +builder.Services.AddHttpContextAccessor(); var app = builder.Build(); diff --git a/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj b/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj index 4f17551..ce8c7ed 100644 --- a/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj +++ b/test/Cnblogs.Architecture.IntegrationTests/Cnblogs.Architecture.IntegrationTests.csproj @@ -1,5 +1,7 @@ - - + + + disable + diff --git a/test/Cnblogs.Architecture.IntegrationTests/DaprTests.cs b/test/Cnblogs.Architecture.IntegrationTests/DaprTests.cs index e0dced1..1d9be35 100644 --- a/test/Cnblogs.Architecture.IntegrationTests/DaprTests.cs +++ b/test/Cnblogs.Architecture.IntegrationTests/DaprTests.cs @@ -32,8 +32,9 @@ public async Task Dapr_SubscribeEndpoint_OkAsync() var response = await httpClient.GetAsync("/dapr/subscribe"); // Assert - response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Should().BeSuccessful(); var responseText = await response.Content.ReadAsStringAsync(); + Debug.WriteLine(responseText); responseText.Should().Contain(nameof(TestIntegrationEvent)); } diff --git a/test/Cnblogs.Architecture.IntegrationTests/DddWebTestCollection.cs b/test/Cnblogs.Architecture.IntegrationTests/DddWebTestCollection.cs deleted file mode 100644 index 3ddac04..0000000 --- a/test/Cnblogs.Architecture.IntegrationTests/DddWebTestCollection.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Cnblogs.Architecture.IntegrationTests; - -[CollectionDefinition(Name)] -public class DddWebTestCollection : ICollectionFixture -{ - public const string Name = nameof(DddWebTestCollection); -} diff --git a/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventHandlerTests.cs b/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventHandlerTests.cs new file mode 100644 index 0000000..51c7e66 --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTests/IntegrationEventHandlerTests.cs @@ -0,0 +1,55 @@ +using System.Diagnostics; +using System.IO.Pipes; +using System.Net; +using System.Net.Http.Json; +using Cnblogs.Architecture.IntegrationTestProject; +using Cnblogs.Architecture.IntegrationTestProject.EventHandlers; +using Cnblogs.Architecture.TestIntegrationEvents; +using FluentAssertions; +using MediatR; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.DependencyInjection; + +namespace Cnblogs.Architecture.IntegrationTests; + +[Collection(IntegrationTestCollection.Name)] +public class IntegrationEventHandlerTests +{ + private readonly IntegrationTestFactory _factory; + + public IntegrationEventHandlerTests(IntegrationTestFactory factory) + { + _factory = factory; + } + + [Fact] + public async Task IntegrationEventHandler_TestIntegrationEvent_SuccessAsync() + { + // Arrange + var client = _factory.CreateClient(); + + // Act + var subscriptions = await client.GetFromJsonAsync("/dapr/subscribe"); + + // Assert + subscriptions.Should().NotBeNullOrEmpty(); + + // Act + var sub = subscriptions.FirstOrDefault(s => s.Route.Contains(nameof(TestIntegrationEvent))); + + // Assert + sub.Should().NotBeNull(); + + Debug.WriteLine("Subscription Route: " + sub.Route); + + // Act + var @event = new TestIntegrationEvent(Guid.NewGuid(), DateTimeOffset.Now, "Hello World!"); + var response = await client.PostAsJsonAsync(sub.Route, @event); + + // Assert + response.Should().BeSuccessful(); + Assert.True(response.Headers.TryGetValues(Constants.IntegrationEventIdHeaderName, out var values)); + values.First().Should().Be(@event.Id.ToString()); + } +} \ No newline at end of file diff --git a/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestCollection.cs b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestCollection.cs new file mode 100644 index 0000000..3ad7ace --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestCollection.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.Architecture.IntegrationTests; + +[CollectionDefinition(Name)] +public class IntegrationTestCollection : ICollectionFixture +{ + public const string Name = nameof(IntegrationTestCollection); +} diff --git a/test/Cnblogs.Architecture.IntegrationTests/DddWebTestFactory.cs b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFactory.cs similarity index 68% rename from test/Cnblogs.Architecture.IntegrationTests/DddWebTestFactory.cs rename to test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFactory.cs index 784c68a..b638297 100644 --- a/test/Cnblogs.Architecture.IntegrationTests/DddWebTestFactory.cs +++ b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFactory.cs @@ -3,6 +3,6 @@ namespace Cnblogs.Architecture.IntegrationTests; -public class DddWebTestFactory : WebApplicationFactory +public class IntegrationTestFactory : WebApplicationFactory { } diff --git a/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFramework.cs b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFramework.cs new file mode 100644 index 0000000..d2b7b04 --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTests/IntegrationTestFramework.cs @@ -0,0 +1,19 @@ +using System.Diagnostics; +using System.Text; +using Cnblogs.Architecture.IntegrationTests; +using Xunit.Abstractions; +using Xunit.Sdk; + +[assembly: TestFramework($"Cnblogs.Architecture.IntegrationTests.{nameof(IntegrationTestFramework)}", "Cnblogs.Architecture.IntegrationTests")] + +namespace Cnblogs.Architecture.IntegrationTests; + +public class IntegrationTestFramework : XunitTestFramework +{ + public IntegrationTestFramework(IMessageSink messageSink) + : base(messageSink) + { + Console.OutputEncoding = Encoding.UTF8; + Trace.Listeners.Add(new ConsoleTraceListener()); + } +} diff --git a/test/Cnblogs.Architecture.IntegrationTests/Subscription.cs b/test/Cnblogs.Architecture.IntegrationTests/Subscription.cs new file mode 100644 index 0000000..2fe8215 --- /dev/null +++ b/test/Cnblogs.Architecture.IntegrationTests/Subscription.cs @@ -0,0 +1,22 @@ +namespace Cnblogs.Architecture.IntegrationTests; + +/// +/// This class defines subscribe endpoint response for dapr +/// +internal class Subscription +{ + /// + /// Gets or sets the topic name. + /// + public string Topic { get; set; } = string.Empty; + + /// + /// Gets or sets the pubsub name + /// + public string PubsubName { get; set; } = string.Empty; + + /// + /// Gets or sets the route + /// + public string Route { get; set; } = string.Empty; +} diff --git a/test/Cnblogs.Architecture.TestIntegrationEvents/TestIntegrationEvent.cs b/test/Cnblogs.Architecture.TestIntegrationEvents/TestIntegrationEvent.cs index 14df8dd..6e76c83 100644 --- a/test/Cnblogs.Architecture.TestIntegrationEvents/TestIntegrationEvent.cs +++ b/test/Cnblogs.Architecture.TestIntegrationEvents/TestIntegrationEvent.cs @@ -2,4 +2,4 @@ namespace Cnblogs.Architecture.TestIntegrationEvents; -public record TestIntegrationEvent(Guid Id, DateTimeOffset CreatedTime) : IntegrationEvent(Id, CreatedTime); \ No newline at end of file +public record TestIntegrationEvent(Guid Id, DateTimeOffset CreatedTime, string Message) : IntegrationEvent(Id, CreatedTime); \ No newline at end of file