From 829811836150cfe05e45e9c3c3531c6b5c27836a Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Mon, 16 Sep 2024 15:49:40 +0200 Subject: [PATCH 1/2] :speech_balloon: chore --- .nuget/Codebelt.Extensions.Xunit.App/README.md | 3 +-- .nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md | 3 +-- .../Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt | 2 +- .nuget/Codebelt.Extensions.Xunit.Hosting/README.md | 3 +-- CHANGELOG.md | 2 +- src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs | 4 +++- 6 files changed, 8 insertions(+), 9 deletions(-) diff --git a/.nuget/Codebelt.Extensions.Xunit.App/README.md b/.nuget/Codebelt.Extensions.Xunit.App/README.md index f8b9055..8d853f1 100644 --- a/.nuget/Codebelt.Extensions.Xunit.App/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.App/README.md @@ -1,7 +1,6 @@ ## About -An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof. -Your ideal companion for .NET 8 and .NET 6. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md index 3e7107b..5f73c34 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md @@ -1,7 +1,6 @@ ## About -An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof. -Your ideal companion for .NET 8 and .NET 6. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt index 444b1bf..4251c9d 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt @@ -6,7 +6,7 @@ Availability: .NET 8, .NET 6 and .NET Standard 2.0   # New Features - ADDED ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService -- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} +- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor, AddXunitTestOutputHelperAccessor{T} and an overload of AddXunitTestLogging   Version 8.3.2 Availability: .NET 8, .NET 6 and .NET Standard 2.0 diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md b/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md index 04bf87e..01cca9d 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md @@ -1,7 +1,6 @@ ## About -An open-source project (MIT license) that targets and complements the Microsoft .NET platform. It provides vast ways of possibilities for all breeds of coders, programmers, developers and the likes thereof. -Your ideal companion for .NET 8, .NET 7, .NET 6, .NET Standard 2 and .NET Framework 4.6.2 and newer. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. It is, by heart, free, flexible and built to extend and boost your agile codebelt. diff --git a/CHANGELOG.md b/CHANGELOG.md index f5986ed..265508c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba - ITestOutputHelperAccessor interface in the Codebelt.Extensions.Xunit namespace that provides access to the ITestOutputHelper instance - TestOutputHelperAccessor class in the Codebelt.Extensions.Xunit namespace that provides a default implementation of the ITestOutputHelper interface - ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService -- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was extended with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} +- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was extended with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor, AddXunitTestOutputHelperAccessor{T} and an overload of AddXunitTestLogging ### Changed diff --git a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs index 90943b9..7a7e13b 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs @@ -2,7 +2,9 @@ using System.Collections; using System.Linq; using Cuemon; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Xunit.Abstractions; namespace Codebelt.Extensions.Xunit.Hosting { @@ -12,7 +14,7 @@ namespace Codebelt.Extensions.Xunit.Hosting public static class LoggerExtensions { /// - /// Returns the associated that is provided when settings up services from . + /// Returns the associated that is provided when settings up services from either or . /// /// The from which to retrieve the . /// Returns an implementation of with all logged entries expressed as . From d365bc3e3f44fbaa3b5a2166f43dd464998651c4 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Mon, 16 Sep 2024 15:50:29 +0200 Subject: [PATCH 2/2] :ambulance: added an additional overload of AddXunitTestLogging (for both back- and forward compatibility) --- .../ServiceCollectionExtensions.cs | 29 +++++++++-- .../AspNetCoreHostTestTest.cs | 7 ++- ...ions.Xunit.Hosting.AspNetCore.Tests.csproj | 2 +- .../WebHostTestFactoryTest.cs | 51 +++++++++++++++++-- 4 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs index 328c5da..8681215 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs @@ -33,15 +33,38 @@ public static IServiceCollection AddXunitTestLogging(this IServiceCollection ser }); return services; } + + /// + /// Adds a unit test optimized implementation of output logging to the collection. + /// + /// The to extend. + /// The that provides access to the output for the logging. + /// The that specifies the minimum level to include for the logging. + /// A reference to so that additional configuration calls can be chained. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static IServiceCollection AddXunitTestLogging(this IServiceCollection services, ITestOutputHelperAccessor accessor, LogLevel minimumLevel = LogLevel.Trace) + { + Validator.ThrowIfNull(services); + Validator.ThrowIfNull(accessor); + services.AddLogging(builder => + { + builder.SetMinimumLevel(minimumLevel); + builder.AddProvider(new XunitTestLoggerProvider(accessor)); + }); + return services; + } /// /// Adds a default implementation of to the collection. /// /// The to extend. /// A reference to so that additional configuration calls can be chained. - public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceCollection services) + public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor(this IServiceCollection services) { - services.AddXunitTestOutputHelperAccessor(); + services.AddXunitTestLoggingOutputHelperAccessor(); return services; } @@ -54,7 +77,7 @@ public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceC /// /// cannot be null. /// - public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceCollection services) where T : class, ITestOutputHelperAccessor + public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor(this IServiceCollection services) where T : class, ITestOutputHelperAccessor { Validator.ThrowIfNull(services); services.AddSingleton(); diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs index 296dca2..45b3d6a 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs @@ -34,6 +34,9 @@ public async Task ShouldHaveResultOfBoolMiddlewareInBody() Assert.Equal("Hello awesome developers!", context!.Response.Body.ToEncodedString(o => o.LeaveOpen = true)); + var logger = _pipeline.ApplicationServices.GetRequiredService>(); + logger.LogInformation("Hello from {0}", nameof(ShouldHaveResultOfBoolMiddlewareInBody)); + await pipeline(context); Assert.Equal("A:True, B:False, C:True, D:False, E:True, F:False", context.Response.Body.ToEncodedString()); @@ -68,8 +71,8 @@ public override void ConfigureServices(IServiceCollection services) o.C = true; o.E = true; }); - services.AddXunitTestOutputHelperAccessor(); - services.AddXunitTestLogging(TestOutput); + services.AddXunitTestLoggingOutputHelperAccessor(); + services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput)); } } } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj index 4e31fe3..fa81a2b 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs index 1cec236..5ff5818 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs @@ -1,5 +1,13 @@ using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; using System.Threading.Tasks; +using Cuemon.AspNetCore.Diagnostics; +using Cuemon.Extensions.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; using Xunit; using Xunit.Abstractions; @@ -12,13 +20,13 @@ public WebHostTestFactoryTest(ITestOutputHelper output) : base(output) } [Fact] - public void CreateMiddlewareTest_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest() + public void Create_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest() { Type sut1 = GetType(); string sut2 = null; var middleware = WebHostTestFactory.Create(Assert.NotNull, Assert.NotNull, host => { - host.ConfigureAppConfiguration((context, configuration) => + host.ConfigureAppConfiguration((context, _) => { sut2 = context.HostingEnvironment.ApplicationName; }); @@ -29,11 +37,11 @@ public void CreateMiddlewareTest_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTe } [Fact] - public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly() + public Task RunAsync_ShouldHaveApplicationNameEqualToThisAssembly() { return WebHostTestFactory.RunAsync(Assert.NotNull, Assert.NotNull, host => { - host.ConfigureAppConfiguration((context, configuration) => + host.ConfigureAppConfiguration((context, _) => { TestOutput.WriteLine(context.HostingEnvironment.ApplicationName); Assert.Equal(GetType().Assembly.GetName().Name, context.HostingEnvironment.ApplicationName); @@ -42,7 +50,7 @@ public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly() } [Fact] - public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext() + public Task RunWithHostBuilderContextAsync_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext() { return WebHostTestFactory.RunWithHostBuilderContextAsync((context, app) => { @@ -69,5 +77,38 @@ public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly_WithH }); }); } + + [Fact] + public async Task RunAsync_ShouldWorkWithXunitTestLogging() + { + using var response = await WebHostTestFactory.RunAsync( + services => + { + services.AddXunitTestLogging(TestOutput); + services.AddServerTiming(o => o.SuppressHeaderPredicate = _ => false); + } + , app => + { + app.UseServerTiming(); + app.Use(async (context, next) => + { + var sw = Stopwatch.StartNew(); + context.Response.OnStarting(() => + { + sw.Stop(); + context.RequestServices.GetRequiredService().AddServerTiming("use-middleware", sw.Elapsed); + return Task.CompletedTask; + }); + await next(context).ConfigureAwait(false); + }); + app.Run(context => + { + Thread.Sleep(400); + return context.Response.WriteAsync("Hello World!"); + }); + }).ConfigureAwait(false); + + Assert.StartsWith("use-middleware;dur=", response.Headers.Single(kvp => kvp.Key == ServerTiming.HeaderName).Value.FirstOrDefault()); + } } }