From 2317832b206c85ff232f17b0ef876979c1df7560 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 17:24:00 +0200 Subject: [PATCH 1/7] :bug: fixed behavioral change for HostTest and AspNetCoreHostTest --- .../AspNetCoreHostTest.cs | 26 +++++++++++++++- .../WebHostTest.cs | 4 +-- .../GenericHostTest.cs | 4 +-- .../HostTest.cs | 30 ++++++++++++++++++- 4 files changed, 58 insertions(+), 6 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostTest.cs index 3dbd6d3..30ec17a 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostTest.cs @@ -19,10 +19,34 @@ public abstract class AspNetCoreHostTest : HostTest where T : class, IAspN /// An implementation of the interface. /// An implementation of the interface. /// The of caller that ends up invoking this instance. - protected AspNetCoreHostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) + protected AspNetCoreHostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : this(false, hostFixture, output, callerType) { } + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether to skip the host fixture initialization. + /// An implementation of the interface. + /// An implementation of the interface. + /// The of caller that ends up invoking this instance. + protected AspNetCoreHostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(skipHostFixtureInitialization, hostFixture, output, callerType) + { + if (skipHostFixtureInitialization) { return; } + if (!hostFixture.HasValidState()) + { + hostFixture.ConfigureHostCallback = ConfigureHost; + hostFixture.ConfigureCallback = Configure; + hostFixture.ConfigureServicesCallback = ConfigureServices; + hostFixture.ConfigureApplicationCallback = ConfigureApplication; + hostFixture.ConfigureHost(this); + } + Host = hostFixture.Host; + ServiceProvider = hostFixture.Host.Services; + Application = hostFixture.Application; + Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); + } + /// /// Gets the initialized by the . /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs index 66154f3..a0cb6f7 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs @@ -14,7 +14,7 @@ internal sealed class WebHostTest : AspNetCoreHostTest, private readonly Action _hostConfigurator; private HostBuilderContext _hostBuilderContext; - internal WebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IAspNetCoreHostFixture hostFixture) : base(hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal WebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IAspNetCoreHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfigurator = serviceConfigurator; _pipelineConfigurator = pipelineConfigurator; @@ -22,7 +22,7 @@ internal WebHostTest(Action serviceConfigurator, Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IAspNetCoreHostFixture hostFixture) : base(hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal WebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IAspNetCoreHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfiguratorWithContext = serviceConfigurator; _pipelineConfiguratorWithContext = pipelineConfigurator; diff --git a/src/Codebelt.Extensions.Xunit.Hosting/GenericHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting/GenericHostTest.cs index db25f7d..227b483 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/GenericHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/GenericHostTest.cs @@ -11,14 +11,14 @@ internal sealed class GenericHostTest : HostTest, IGenericHostTest private readonly Action _hostConfigurator; private HostBuilderContext _hostBuilderContext; - internal GenericHostTest(Action serviceConfigurator, Action hostConfigurator, IHostFixture hostFixture) : base(hostFixture, callerType: serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal GenericHostTest(Action serviceConfigurator, Action hostConfigurator, IHostFixture hostFixture) : base(true, hostFixture, callerType: serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfigurator = serviceConfigurator; _hostConfigurator = hostConfigurator; InitializeHostFixture(hostFixture); } - internal GenericHostTest(Action serviceConfigurator, Action hostConfigurator, IHostFixture hostFixture) : base(hostFixture, callerType: serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal GenericHostTest(Action serviceConfigurator, Action hostConfigurator, IHostFixture hostFixture) : base(true, hostFixture, callerType: serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfiguratorWithContext = serviceConfigurator; _hostConfigurator = hostConfigurator; diff --git a/src/Codebelt.Extensions.Xunit.Hosting/HostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting/HostTest.cs index 1dfb236..f197eef 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/HostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/HostTest.cs @@ -22,9 +22,37 @@ public abstract class HostTest : Test, IClassFixture where T : class, IHos /// An implementation of the interface. /// An implementation of the interface. /// The of caller that ends up invoking this instance. - protected HostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(output, callerType) + /// + /// is null. + /// + protected HostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : this(false, hostFixture, output, callerType) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// A value indicating whether to skip the host fixture initialization. + /// An implementation of the interface. + /// An implementation of the interface. + /// The of caller that ends up invoking this instance. + /// + /// is null. + /// + protected HostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(output, callerType) { if (hostFixture == null) { throw new ArgumentNullException(nameof(hostFixture)); } + if (skipHostFixtureInitialization) { return; } + if (!hostFixture.HasValidState()) + { + hostFixture.ConfigureHostCallback = ConfigureHost; + hostFixture.ConfigureCallback = Configure; + hostFixture.ConfigureServicesCallback = ConfigureServices; + hostFixture.ConfigureHost(this); + } + Host = hostFixture.Host; + ServiceProvider = hostFixture.Host.Services; + Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); } /// From a9fcf713d63372c04b50a3f0a4ed4491ce0089fb Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 17:26:36 +0200 Subject: [PATCH 2/7] :wrench: aligned IHostEnvironment.ApplicationName with AspNetCoreHostFixture --- .../HostFixture.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs index 02f92be..2f24dac 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; @@ -56,14 +57,21 @@ public virtual void ConfigureHost(Test hostTest) Configuration = context.Configuration; HostingEnvironment = context.HostingEnvironment; ConfigureServicesCallback(services); + }) + .ConfigureHostConfiguration(builder => + { + builder.AddInMemoryCollection(new Dictionary + { + { HostDefaults.ApplicationKey, hostTest.CallerType.Assembly.GetName().Name } + }); }); #if NET9_0_OR_GREATER - hb.UseDefaultServiceProvider(o => - { - o.ValidateOnBuild = true; - o.ValidateScopes = true; - }); + hb.UseDefaultServiceProvider(o => + { + o.ValidateOnBuild = true; + o.ValidateScopes = true; + }); #endif ConfigureHostCallback(hb); From aa6a2418c854a36399ac4b2148b28f30ea6bb151 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 20:38:00 +0200 Subject: [PATCH 3/7] :bug: fixed behavioral change for GetTestStore extension methods --- .../LoggerExtensions.cs | 10 ++++++---- .../XunitTestLogger.cs | 4 +++- .../XunitTestLoggerProvider.cs | 9 ++++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs index a263944..5695646 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs @@ -15,6 +15,7 @@ public static class LoggerExtensions /// Returns the associated that is provided when settings up services from . /// /// The from which to retrieve the . + /// The category name for messages produced by the -or- null for messages produced by all loggers. /// Returns an implementation of with all logged entries expressed as . /// /// cannot be null. @@ -22,7 +23,7 @@ public static class LoggerExtensions /// /// does not contain a test store. /// - public static ITestStore GetTestStore(this ILogger logger) + public static ITestStore GetTestStore(this ILogger logger, string categoryName = null) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } var loggerType = logger.GetType(); @@ -41,7 +42,9 @@ public static ITestStore GetTestStore(this ILogger logger) { var xunitTestLogger = loggerInformationType.GetProperty("Logger")?.GetValue(loggerInformation) as XunitTestLogger; if (xunitTestLogger == null) { continue; } - return xunitTestLogger.Provider; + return categoryName == null + ? xunitTestLogger.Provider + : xunitTestLogger.Provider[categoryName]; } } } @@ -60,10 +63,9 @@ public static ITestStore GetTestStore(this ILogger logger) /// /// does not contain a test store. /// - [Obsolete($"This method will be removed in a future version. Please use non-generic equivalent {nameof(GetTestStore)}.")] public static ITestStore GetTestStore(this ILogger logger) { - return GetTestStore((ILogger)logger); + return GetTestStore(logger, typeof(T).FullName); } } } diff --git a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs index 0bd8df3..aae9ec2 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs @@ -5,7 +5,7 @@ namespace Codebelt.Extensions.Xunit.Hosting { - internal sealed class XunitTestLogger : ILogger, IDisposable + internal sealed class XunitTestLogger : InMemoryTestStore, ILogger, IDisposable { private readonly ITestOutputHelperAccessor _accessor; private readonly ITestOutputHelper _output; @@ -32,6 +32,8 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except _provider.WriteLoggerEntry(logLevel, eventId, message); + Add(new XunitTestLoggerEntry(logLevel, eventId, message)); + if (_accessor != null) { if (_accessor.TestOutput == null) { throw new InvalidOperationException($"{nameof(ITestOutputHelperAccessor)}.{nameof(ITestOutputHelperAccessor.TestOutput)} is null."); } diff --git a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs index f01ef22..67fe0f8 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs @@ -1,4 +1,5 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; using Microsoft.Extensions.Logging; using Xunit.Abstractions; @@ -6,7 +7,7 @@ namespace Codebelt.Extensions.Xunit.Hosting { internal sealed class XunitTestLoggerProvider : InMemoryTestStore, ILoggerProvider { - private readonly ConcurrentDictionary _loggers = new(); + private readonly ConcurrentDictionary _loggers = new(StringComparer.OrdinalIgnoreCase); private readonly ITestOutputHelperAccessor _accessor; private readonly ITestOutputHelper _output; @@ -26,12 +27,14 @@ public ILogger CreateLogger(string categoryName) ? new XunitTestLogger(this, _accessor) : new XunitTestLogger(this, _output)); } - + public void WriteLoggerEntry(LogLevel logLevel, EventId eventId, string message) { Add(new XunitTestLoggerEntry(logLevel, eventId, message)); } + public ITestStore this[string categoryName] => _loggers[categoryName]; + public void Dispose() { } From ed28645bf9ca283c4d0649fbd9a881b3681933bb Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 20:38:24 +0200 Subject: [PATCH 4/7] :white_check_mark: added new / updated existing test --- .../AspNetCoreHostTestTest.cs | 13 ----- .../Assets/ValidHostTest.cs | 12 ---- .../MvcAspNetCoreHostTestTest.cs | 13 ----- .../WebHostTestFactoryTest.cs | 2 +- .../Assets/ValidHostTest.cs | 10 ---- .../GenericHostTestFactoryTest.cs | 53 ++++++++++++++++++ .../HostTestTest.cs | 12 ---- .../ServiceCollectionExtensions.cs | 56 ++++++++++++++----- 8 files changed, 96 insertions(+), 75 deletions(-) create mode 100644 test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostTestFactoryTest.cs diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs index 222a13c..07fb254 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs @@ -21,19 +21,6 @@ public class AspNetCoreHostTestTest : AspNetCoreHostTest public AspNetCoreHostTestTest(AspNetCoreHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { - if (!hostFixture.HasValidState()) - { - hostFixture.ConfigureHostCallback = ConfigureHost; - hostFixture.ConfigureCallback = Configure; - hostFixture.ConfigureServicesCallback = ConfigureServices; - hostFixture.ConfigureApplicationCallback = ConfigureApplication; - hostFixture.ConfigureHost(this); - } - Host = hostFixture.Host; - ServiceProvider = hostFixture.Host.Services; - Application = hostFixture.Application; - Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); - _pipeline = hostFixture.Application; _provider = hostFixture.ServiceProvider; _provider.GetRequiredService().TestOutput = output; diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs index e0848a9..544cc78 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs @@ -7,18 +7,6 @@ public class ValidHostTest : AspNetCoreHostTest { public ValidHostTest(AspNetCoreHostFixture hostFixture) : base(hostFixture) { - if (!hostFixture.HasValidState()) - { - hostFixture.ConfigureHostCallback = ConfigureHost; - hostFixture.ConfigureCallback = Configure; - hostFixture.ConfigureServicesCallback = ConfigureServices; - hostFixture.ConfigureApplicationCallback = ConfigureApplication; - hostFixture.ConfigureHost(this); - } - Host = hostFixture.Host; - ServiceProvider = hostFixture.Host.Services; - Application = hostFixture.Application; - Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); } public override void ConfigureServices(IServiceCollection services) diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs index 4a5bbae..bbaeb66 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs @@ -17,19 +17,6 @@ public class MvcAspNetCoreHostTestTest : AspNetCoreHostTest().TestOutput = output; _hostFixture = hostFixture; _client = hostFixture.Host.GetTestClient(); diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs index 99ac85f..1719561 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs @@ -73,7 +73,7 @@ public void Create_ShouldCaptureSecurityException_DueToNonBlockingAspNetCoreHost }); })) { - var loggerStore = startup.ServiceProvider.GetRequiredService>().GetTestStore(); + var loggerStore = startup.ServiceProvider.GetRequiredService>().GetTestStore(null); var message = loggerStore.Query(entry => entry.Severity == LogLevel.Critical && entry.Message.Contains("SecurityException", StringComparison.OrdinalIgnoreCase)).SingleOrDefault()?.Message; Assert.NotNull(message); Assert.Contains("System.Security.SecurityException: Security error.", message); diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs index abbea82..ea8dea5 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs @@ -9,16 +9,6 @@ public class ValidHostTest : HostTest { public ValidHostTest(HostFixture hostFixture) : base(hostFixture) { - if (!hostFixture.HasValidState()) - { - hostFixture.ConfigureHostCallback = ConfigureHost; - hostFixture.ConfigureCallback = Configure; - hostFixture.ConfigureServicesCallback = ConfigureServices; - hostFixture.ConfigureHost(this); - } - Host = hostFixture.Host; - ServiceProvider = hostFixture.Host.Services; - Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); } public override void ConfigureServices(IServiceCollection services) diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostTestFactoryTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostTestFactoryTest.cs new file mode 100644 index 0000000..a7d94f0 --- /dev/null +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostTestFactoryTest.cs @@ -0,0 +1,53 @@ +using System; +using Xunit; +using Xunit.Abstractions; + +namespace Codebelt.Extensions.Xunit.Hosting +{ + public class GenericHostTestFactoryTest : Test + { + public GenericHostTestFactoryTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Create_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest() + { + Type sut1 = GetType(); + string sut2 = null; + var middleware = GenericHostTestFactory.Create(Assert.NotNull, host => + { + host.ConfigureAppConfiguration((context, _) => + { + sut2 = context.HostingEnvironment.ApplicationName; + }); + }); + + Assert.True(sut1 == middleware.CallerType.DeclaringType); + Assert.Equal(GetType().Assembly.GetName().Name, sut2); + } + + + [Fact] + public void CreateWithHostBuilderContext_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext() + { + GenericHostTestFactory.CreateWithHostBuilderContext((context, services) => + { + Assert.NotNull(context); + Assert.NotNull(context.HostingEnvironment); + Assert.NotNull(context.Configuration); + Assert.NotNull(context.Properties); + Assert.NotNull(services); + }, + host => + { + host.ConfigureAppConfiguration((context, configuration) => + { + TestOutput.WriteLine(context.HostingEnvironment.ApplicationName); + Assert.Equal(GetType().Assembly.GetName().Name, context.HostingEnvironment.ApplicationName); + }); + }, + hostFixture: null); + } + } +} diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs index 08a67a8..5f89a32 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs @@ -20,20 +20,8 @@ public class HostTestTest : HostTest public HostTestTest(HostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { - if (!hostFixture.HasValidState()) - { - hostFixture.ConfigureHostCallback = ConfigureHost; - hostFixture.ConfigureCallback = Configure; - hostFixture.ConfigureServicesCallback = ConfigureServices; - hostFixture.ConfigureHost(this); - } - Host = hostFixture.Host; - ServiceProvider = hostFixture.Host.Services; - Configure(hostFixture.Configuration, hostFixture.HostingEnvironment); - _scope = hostFixture.ServiceProvider.CreateScope(); _correlationsFactory = () => _scope.ServiceProvider.GetServices().ToList(); - } [Fact, Priority(1)] diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/ServiceCollectionExtensions.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/ServiceCollectionExtensions.cs index 1324469..65751eb 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/ServiceCollectionExtensions.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/ServiceCollectionExtensions.cs @@ -1,4 +1,6 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Xunit; @@ -13,33 +15,59 @@ public ServiceCollectionExtensions(ITestOutputHelper output) : base(output) } [Fact] - public void AddTestOutputLogging_ShouldAddTestOutputLogging() + public void AddXunitTestLogging_ShouldAddXunitTestLogging() { var services = new ServiceCollection(); services.AddXunitTestLogging(TestOutput); var provider = services.BuildServiceProvider(); - var logger = provider.GetRequiredService>(); - var loggerStore = logger.GetTestStore(); + var logger1 = provider.GetRequiredService>(); + var loggerStore1 = logger1.GetTestStore(); + var loggerStore1Duplicate = logger1.GetTestStore(typeof(ServiceCollectionExtensions).FullName!.ToLowerInvariant()); - logger.LogCritical("SUT"); - logger.LogTrace("SUT"); - logger.LogDebug("SUT"); - logger.LogError("SUT"); - logger.LogInformation("SUT"); - logger.LogWarning("SUT"); + var logger2 = provider.GetRequiredService>(); + var loggerStore2 = logger2.GetTestStore(null); // all loggers - Assert.NotNull(logger); - Assert.NotNull(loggerStore); - Assert.Equal(6, loggerStore.Query().Count()); - Assert.Collection(loggerStore.Query(), + logger1.LogCritical("SUT"); + logger1.LogTrace("SUT"); + logger1.LogDebug("SUT"); + logger1.LogError("SUT"); + logger1.LogInformation("SUT"); + logger1.LogWarning("SUT"); + + logger2.LogInformation("Unique message for logger2."); + + Assert.Throws(() => logger2.GetTestStore("InvalidValue")); + + Assert.Equal(loggerStore1, loggerStore1Duplicate); + + Assert.NotNull(logger1); + Assert.NotNull(loggerStore1); + + Assert.NotNull(logger2); + Assert.NotNull(loggerStore2); + + Assert.Equal(6, loggerStore1.Query().Count()); + Assert.Equal(7, loggerStore2.Query().Count()); + + Assert.Collection(loggerStore1.Query(), entry => Assert.Equal("Critical: SUT", entry.ToString()), entry => Assert.Equal("Trace: SUT", entry.ToString()), entry => Assert.Equal("Debug: SUT", entry.ToString()), entry => Assert.Equal("Error: SUT", entry.ToString()), entry => Assert.Equal("Information: SUT", entry.ToString()), entry => Assert.Equal("Warning: SUT", entry.ToString())); + + Assert.Collection(loggerStore2.Query(), + entry => Assert.Equal("Critical: SUT", entry.ToString()), + entry => Assert.Equal("Trace: SUT", entry.ToString()), + entry => Assert.Equal("Debug: SUT", entry.ToString()), + entry => Assert.Equal("Error: SUT", entry.ToString()), + entry => Assert.Equal("Information: SUT", entry.ToString()), + entry => Assert.Equal("Warning: SUT", entry.ToString()), + entry => Assert.Equal("Information: Unique message for logger2.", entry.ToString())); + } } } From 4c6c5fc2df74dd138436ad8c04079bde5a54d246 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 21:00:37 +0200 Subject: [PATCH 5/7] :package: updated NuGet package definition --- .../PackageReleaseNotes.txt | 8 +++++++- .../PackageReleaseNotes.txt | 11 ++++++++++- .../PackageReleaseNotes.txt | 18 +++++++++++++++++- .../PackageReleaseNotes.txt | 8 +++++++- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/.nuget/Codebelt.Extensions.Xunit.App/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.App/PackageReleaseNotes.txt index 8d9c9cf..2c43fc6 100644 --- a/.nuget/Codebelt.Extensions.Xunit.App/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.App/PackageReleaseNotes.txt @@ -1,4 +1,10 @@ -Version 9.1.0 +Version 9.1.1 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies to latest and greatest with respect to TFMs +  +Version 9.1.0 Availability: .NET 9 and .NET 8   # ALM diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt index df4c078..d82159e 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt @@ -1,4 +1,13 @@ -Version 9.1.0 +Version 9.1.1 +Availability: .NET 9 and .NET 8 +  +# ALM +- CHANGED Dependencies to latest and greatest with respect to TFMs +  +# Bug Fixes +- FIXED AspNetCoreHostTest class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to have same behavior as prior to 9.1.0 release (hereby being backward compatible as originally intended) +  +Version 9.1.0 Availability: .NET 9 and .NET 8   # ALM diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt index e1d2f13..af00175 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt @@ -1,4 +1,20 @@ -Version 9.1.0 +Version 9.1.1 +Availability: .NET 9, .NET 8 and .NET Standard 2.0 +  +# ALM +- CHANGED Dependencies to latest and greatest with respect to TFMs +  +# Bug Fixes +- FIXED HostTest class in the Codebelt.Extensions.Xunit.Hosting namespace to have same behavior as prior to 9.1.0 release (hereby being backward compatible as originally intended) +- FIXED LoggerExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace to have same behavior as prior to 9.1.0 release (hereby being backward compatible as originally intended) +  +# Improvements +- CHANGED HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace so that IHostEnvironment.ApplicationName is aligned with the equivalent logic found in AspNetCoreHostFixture class (e.g., the assembly name of the calling Test type is used as the default value for the ApplicationName property) +  +# New Features +- EXTENDED LoggerExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with one new extension method for the ILogger interface: An overload of GetTestStore that takes an optional string argument (categoryName) +  +Version 9.1.0 Availability: .NET 9, .NET 8 and .NET Standard 2.0   # ALM diff --git a/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt index a302b61..597cc81 100644 --- a/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt @@ -1,4 +1,10 @@ -Version 9.1.0 +Version 9.1.1 +Availability: .NET 9, .NET 8 and .NET Standard 2.0 +  +# ALM +- CHANGED Dependencies to latest and greatest with respect to TFMs +  +Version 9.1.0 Availability: .NET 9, .NET 8 and .NET Standard 2.0   # ALM From 77deecb8a9bd929bf5cde1f638f2ca4599354895 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 21:02:56 +0200 Subject: [PATCH 6/7] :speech_balloon: updated community health pages --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c93d7a7..81771a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,22 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba > [!NOTE] > Changelog entries prior to version 8.4.0 was migrated from previous versions of Cuemon.Extensions.Xunit, Cuemon.Extensions.Xunit.Hosting, and Cuemon.Extensions.Xunit.Hosting.AspNetCore. +## [9.1.1] - 2025-04-01 + +### Added + +- LoggerExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace received one new extension method for the ILogger interface: An overload of GetTestStore that takes an optional string argument (categoryName) + +### Changed + +- HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace so that IHostEnvironment.ApplicationName is aligned with the equivalent logic found in AspNetCoreHostFixture class (e.g., the assembly name of the calling Test type is used as the default value for the ApplicationName property) + +### Fixed + +- HostTest class in the Codebelt.Extensions.Xunit.Hosting namespace to have same behavior as prior to `9.1.0` release (hereby being backward compatible as originally intended) +- LoggerExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace to have same behavior as prior to `9.1.0` release (hereby being backward compatible as originally intended) +- AspNetCoreHostTest class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to have same behavior as prior to 9.1.0 release (hereby being backward compatible as originally intended) + ## [9.1.0] - 2025-03-31 This is a service update that primarily focuses on package dependencies including DIP improvements and a new blocking implementation of the AspNetCoreHostFixture. From de9d1ff11a49233cb8b16f6723a1fb97577342e7 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Tue, 1 Apr 2025 21:27:58 +0200 Subject: [PATCH 7/7] :recycle: applied improvement as suggested by copilot reviewer --- .../LoggerExtensions.cs | 4 ++++ .../XunitTestLoggerProvider.cs | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs index 5695646..230526f 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Extensions.Logging; @@ -23,6 +24,9 @@ public static class LoggerExtensions /// /// does not contain a test store. /// + /// + /// does not contain a test store for the specified . + /// public static ITestStore GetTestStore(this ILogger logger, string categoryName = null) { if (logger == null) { throw new ArgumentNullException(nameof(logger)); } diff --git a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs index 67fe0f8..8ec44fe 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLoggerProvider.cs @@ -1,6 +1,7 @@ -using System; +using Microsoft.Extensions.Logging; +using System; using System.Collections.Concurrent; -using Microsoft.Extensions.Logging; +using System.Collections.Generic; using Xunit.Abstractions; namespace Codebelt.Extensions.Xunit.Hosting @@ -33,7 +34,17 @@ public void WriteLoggerEntry(LogLevel logLevel, EventId eventId, string message) Add(new XunitTestLoggerEntry(logLevel, eventId, message)); } - public ITestStore this[string categoryName] => _loggers[categoryName]; + public ITestStore this[string categoryName] + { + get + { + if (_loggers.TryGetValue(categoryName, out var logger)) + { + return logger; + } + throw new KeyNotFoundException($"Logger for category '{categoryName}' not found."); + } + } public void Dispose() {