From 7cc666b4253473dfc4916f7a840baa843c5179fd Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:09:16 +0200 Subject: [PATCH 01/12] :loud_sound: opt-in to write unhandled exceptions using ITestOutputHelper --- src/Codebelt.Extensions.Xunit/Test.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Codebelt.Extensions.Xunit/Test.cs b/src/Codebelt.Extensions.Xunit/Test.cs index 6994126..7d5139a 100644 --- a/src/Codebelt.Extensions.Xunit/Test.cs +++ b/src/Codebelt.Extensions.Xunit/Test.cs @@ -53,6 +53,14 @@ protected Test(ITestOutputHelper output = null, Type callerType = null) { TestOutput = output; CallerType = callerType ?? GetType(); + + if (output == null) { return; } + + AppDomain.CurrentDomain.UnhandledException += (sender, e) => + { + var exception = e.ExceptionObject as Exception; + output.WriteLine($"Unhandled exception captured: {exception?.Message}"); + }; } /// From c66d40b03004db33be66eb94b8c0183d73280d37 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:14:28 +0200 Subject: [PATCH 02/12] :recycle: renamed default implementations to use the word Managed (due to host being started per default) --- .../HostTestFactory.cs | 8 ++++---- .../{GenericHostFixture.cs => ManagedHostFixture.cs} | 9 +++++---- ...malHostFixture.cs => ManagedMinimalHostFixture.cs} | 11 ++++++----- .../MinimalHostTestFactory.cs | 8 ++++---- 4 files changed, 19 insertions(+), 17 deletions(-) rename src/Codebelt.Extensions.Xunit.Hosting/{GenericHostFixture.cs => ManagedHostFixture.cs} (91%) rename src/Codebelt.Extensions.Xunit.Hosting/{MinimalHostFixture.cs => ManagedMinimalHostFixture.cs} (84%) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/HostTestFactory.cs b/src/Codebelt.Extensions.Xunit.Hosting/HostTestFactory.cs index d02c20c..0962eea 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/HostTestFactory.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/HostTestFactory.cs @@ -14,11 +14,11 @@ public static class HostTestFactory /// /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IHostTest Create(Action serviceSetup = null, Action hostSetup = null, IGenericHostFixture hostFixture = null) { - return new Internal.HostTest(serviceSetup, hostSetup, hostFixture ?? new GenericHostFixture()); + return new Internal.HostTest(serviceSetup, hostSetup, hostFixture ?? new ManagedHostFixture()); } /// @@ -26,11 +26,11 @@ public static IHostTest Create(Action serviceSetup = null, A /// /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IHostTest CreateWithHostBuilderContext(Action serviceSetup = null, Action hostSetup = null, IGenericHostFixture hostFixture = null) { - return new Internal.HostTest(serviceSetup, hostSetup, hostFixture ?? new GenericHostFixture()); + return new Internal.HostTest(serviceSetup, hostSetup, hostFixture ?? new ManagedHostFixture()); } } } diff --git a/src/Codebelt.Extensions.Xunit.Hosting/GenericHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/ManagedHostFixture.cs similarity index 91% rename from src/Codebelt.Extensions.Xunit.Hosting/GenericHostFixture.cs rename to src/Codebelt.Extensions.Xunit.Hosting/ManagedHostFixture.cs index 2fe2d1d..435293a 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/GenericHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/ManagedHostFixture.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Threading; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -12,12 +13,12 @@ namespace Codebelt.Extensions.Xunit.Hosting /// /// /// - public class GenericHostFixture : HostFixture, IGenericHostFixture + public class ManagedHostFixture : HostFixture, IGenericHostFixture { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public GenericHostFixture() + public ManagedHostFixture() { } @@ -75,7 +76,7 @@ public virtual void ConfigureHost(Test hostTest) Host = hb.Build(); - HostRunnerCallback(Host); + AsyncHostRunnerCallback(Host, CancellationToken.None); } /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/ManagedMinimalHostFixture.cs similarity index 84% rename from src/Codebelt.Extensions.Xunit.Hosting/MinimalHostFixture.cs rename to src/Codebelt.Extensions.Xunit.Hosting/ManagedMinimalHostFixture.cs index b89b747..bf01d9a 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/ManagedMinimalHostFixture.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using Microsoft.Extensions.Hosting; namespace Codebelt.Extensions.Xunit.Hosting @@ -8,13 +9,13 @@ namespace Codebelt.Extensions.Xunit.Hosting /// /// /// - /// This is the "modern" minimal style implementation of . - public class MinimalHostFixture : HostFixture, IMinimalHostFixture + /// This is the "modern" minimal style implementation of . + public class ManagedMinimalHostFixture : HostFixture, IMinimalHostFixture { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public MinimalHostFixture() + public ManagedMinimalHostFixture() { } @@ -49,7 +50,7 @@ public virtual void ConfigureHost(Test hostTest) Host = hb.Build(); - HostRunnerCallback(Host); + AsyncHostRunnerCallback(Host, CancellationToken.None); } /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostTestFactory.cs b/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostTestFactory.cs index ff7cff7..340993a 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostTestFactory.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/MinimalHostTestFactory.cs @@ -14,11 +14,11 @@ public static class MinimalHostTestFactory /// /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IHostTest Create(Action serviceSetup = null, Action hostSetup = null, IMinimalHostFixture hostFixture = null) { - return new Internal.MinimalHostTest(serviceSetup, hostSetup, hostFixture ?? new MinimalHostFixture()); + return new Internal.MinimalHostTest(serviceSetup, hostSetup, hostFixture ?? new ManagedMinimalHostFixture()); } /// @@ -26,11 +26,11 @@ public static IHostTest Create(Action serviceSetup = null, A /// /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IHostTest CreateWithHostBuilderContext(Action serviceSetup = null, Action hostSetup = null, IMinimalHostFixture hostFixture = null) { - return new Internal.MinimalHostTest(serviceSetup, hostSetup, hostFixture ?? new MinimalHostFixture()); + return new Internal.MinimalHostTest(serviceSetup, hostSetup, hostFixture ?? new ManagedMinimalHostFixture()); } } } From 56eb26dac1962c0056768bc09dd0423204add9b6 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:16:41 +0200 Subject: [PATCH 03/12] :building_construction: opt-in for async host runner callback (still trying to avoid deadlocks) --- .../HostFixture.cs | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs index a87138a..1c3a55d 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.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; @@ -13,12 +14,21 @@ namespace Codebelt.Extensions.Xunit.Hosting public abstract class HostFixture : IHostFixture, IAsyncLifetime { private readonly object _lock = new(); - private Action _hostRunnerCallback = host => + private Func _asyncHostRunnerCallback = async (host, cancellationToken) => { - Task.Run(() => host.StartAsync().ConfigureAwait(false)) // this was done to reduce the risk of deadlocks (https://www.strathweb.com/2021/05/the-curious-case-of-asp-net-core-integration-test-deadlock/) - .ConfigureAwait(false) - .GetAwaiter() - .GetResult(); + if (SynchronizationContext.Current == null) + { + await host.StartAsync(cancellationToken).ConfigureAwait(false); + } + else + { + Task.Run(async () => + { + await host.StartAsync(cancellationToken).ConfigureAwait(false); + }).GetAwaiter().GetResult(); + } + + // this was done to reduce the risk of deadlocks (https://stackoverflow.com/questions/50918647/why-does-this-xunit-test-deadlock-on-a-single-cpu-vm/50953607#50953607) }; /// @@ -56,10 +66,10 @@ protected static bool HasTypes(Type type, params Type[] types) /// /// cannot be null. /// - protected Action HostRunnerCallback + protected Func AsyncHostRunnerCallback { - get => _hostRunnerCallback; - set => _hostRunnerCallback = value ?? throw new ArgumentNullException(nameof(value), "The host runner delegate cannot be null."); + get => _asyncHostRunnerCallback; + set => _asyncHostRunnerCallback = value ?? throw new ArgumentNullException(nameof(value), "The host runner delegate cannot be null."); } /// From f0a473ea37e41819c9119f3ad55eba9a41761166 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:17:45 +0200 Subject: [PATCH 04/12] :sparkles: added self-managed variants of managed host fixtures --- .../SelfManagedHostFixture.cs | 21 +++++++++++++++++++ .../SelfManagedMinimalHostFixture.cs | 21 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/Codebelt.Extensions.Xunit.Hosting/SelfManagedHostFixture.cs create mode 100644 src/Codebelt.Extensions.Xunit.Hosting/SelfManagedMinimalHostFixture.cs diff --git a/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedHostFixture.cs new file mode 100644 index 0000000..d68cbdf --- /dev/null +++ b/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedHostFixture.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; + +namespace Codebelt.Extensions.Xunit.Hosting +{ + /// + /// Represents a self-managed implementation of the class. + /// + public sealed class SelfManagedHostFixture : ManagedHostFixture + { + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor sets the to a no-op asynchronous delegate. + /// + public SelfManagedHostFixture() + { + AsyncHostRunnerCallback = (_, __) => Task.CompletedTask; + } + } +} diff --git a/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedMinimalHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedMinimalHostFixture.cs new file mode 100644 index 0000000..8090797 --- /dev/null +++ b/src/Codebelt.Extensions.Xunit.Hosting/SelfManagedMinimalHostFixture.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; + +namespace Codebelt.Extensions.Xunit.Hosting +{ + /// + /// Represents a self-managed implementation of the class. + /// + public sealed class SelfManagedMinimalHostFixture : ManagedMinimalHostFixture + { + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor sets the to a no-op asynchronous delegate. + /// + public SelfManagedMinimalHostFixture() + { + AsyncHostRunnerCallback = (_, __) => Task.CompletedTask; + } + } +} From 944ab3e6958923813fae0d72b06fb899ee36b70e Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:28:19 +0200 Subject: [PATCH 05/12] :recycle: renamed default implementations to use the word Managed (due to web host being started per default) --- ...ostFixture.cs => ManagedWebHostFixture.cs} | 11 +++++----- ...ure.cs => ManagedWebMinimalHostFixture.cs} | 17 ++++++++-------- .../MinimalWebHostTestFactory.cs | 20 +++++++++---------- .../WebHostTestFactory.cs | 12 +++++------ 4 files changed, 31 insertions(+), 29 deletions(-) rename src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/{WebHostFixture.cs => ManagedWebHostFixture.cs} (91%) rename src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/{MinimalWebHostFixture.cs => ManagedWebMinimalHostFixture.cs} (80%) diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs similarity index 91% rename from src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostFixture.cs rename to src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs index 502ff04..05cb73c 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebHostFixture.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting.StaticWebAssets; @@ -13,14 +14,14 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore /// /// Provides a default implementation of the interface. /// - /// + /// /// - public class WebHostFixture : GenericHostFixture, IWebHostFixture + public class ManagedWebHostFixture : ManagedHostFixture, IWebHostFixture { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public WebHostFixture() + public ManagedWebHostFixture() { } @@ -91,7 +92,7 @@ public override void ConfigureHost(Test hostTest) Host = hb.Build(); - HostRunnerCallback(Host); + AsyncHostRunnerCallback(Host, CancellationToken.None); } /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs similarity index 80% rename from src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixture.cs rename to src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs index 05e2ce9..663d084 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/ManagedWebMinimalHostFixture.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.Hosting; @@ -6,17 +7,17 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { /// - /// Provides a default implementation of the interface. + /// Provides a default implementation of the interface. /// - /// - /// - /// This is the "modern" minimal style implementation of . - public class MinimalWebHostFixture : MinimalHostFixture, IMinimalWebHostFixture + /// + /// + /// This is the "modern" minimal style implementation of . + public class ManagedWebMinimalHostFixture : ManagedMinimalHostFixture, IWebMinimalHostFixture { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - public MinimalWebHostFixture() + public ManagedWebMinimalHostFixture() { } @@ -58,7 +59,7 @@ public override void ConfigureHost(Test hostTest) Host = webApplication; - HostRunnerCallback(Host); + AsyncHostRunnerCallback(Host, CancellationToken.None); } /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTestFactory.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTestFactory.cs index c13e3c1..05780f8 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTestFactory.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTestFactory.cs @@ -21,11 +21,11 @@ public static class MinimalWebHostTestFactory /// The which may be configured. /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. - public static IWebHostTest Create(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IMinimalWebHostFixture hostFixture = null) + public static IWebHostTest Create(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IWebMinimalHostFixture hostFixture = null) { - return new MinimalWebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new MinimalWebHostFixture()); + return new MinimalWebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new ManagedWebMinimalHostFixture()); } /// @@ -34,11 +34,11 @@ public static IWebHostTest Create(Action serviceSetup = null /// The which may be configured. /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. - public static IWebHostTest CreateWithHostBuilderContext(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IMinimalWebHostFixture hostFixture = null) + public static IWebHostTest CreateWithHostBuilderContext(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IWebMinimalHostFixture hostFixture = null) { - return new MinimalWebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new MinimalWebHostFixture()); + return new MinimalWebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new ManagedWebMinimalHostFixture()); } /// @@ -48,9 +48,9 @@ public static IWebHostTest CreateWithHostBuilderContext(ActionThe which may be configured. /// The which may be configured. /// The function delegate that creates a from the . Default is a GET request to the root URL ("/"). - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// A that represents the asynchronous operation. The task result contains the for the test server. - public static async Task RunAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IMinimalWebHostFixture hostFixture = null) + public static async Task RunAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IWebMinimalHostFixture hostFixture = null) { using var client = Create(serviceSetup, pipelineSetup, hostSetup, hostFixture).Host.GetTestClient(); return await client.ToHttpResponseMessageAsync(responseFactory).ConfigureAwait(false); @@ -63,9 +63,9 @@ public static async Task RunAsync(ActionThe which may be configured. /// The which may be configured. /// The function delegate that creates a from the . Default is a GET request to the root URL ("/"). - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// A that represents the asynchronous operation. The task result contains the for the test server. - public static async Task RunWithHostBuilderContextAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IMinimalWebHostFixture hostFixture = null) + public static async Task RunWithHostBuilderContextAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IWebMinimalHostFixture hostFixture = null) { using var client = CreateWithHostBuilderContext(serviceSetup, pipelineSetup, hostSetup, hostFixture).Host.GetTestClient(); return await client.ToHttpResponseMessageAsync(responseFactory).ConfigureAwait(false); diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs index 23536cf..68131f8 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTestFactory.cs @@ -21,11 +21,11 @@ public static class WebHostTestFactory /// The which may be configured. /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IWebHostTest Create(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IWebHostFixture hostFixture = null) { - return new WebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new WebHostFixture()); + return new WebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new ManagedWebHostFixture()); } /// @@ -34,11 +34,11 @@ public static IWebHostTest Create(Action serviceSetup = null /// The which may be configured. /// The which may be configured. /// The which may be configured. - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// An instance of an implementation. public static IWebHostTest CreateWithHostBuilderContext(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, IWebHostFixture hostFixture = null) { - return new WebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new WebHostFixture()); + return new WebHostTest(serviceSetup, pipelineSetup, hostSetup, hostFixture ?? new ManagedWebHostFixture()); } /// @@ -48,7 +48,7 @@ public static IWebHostTest CreateWithHostBuilderContext(ActionThe which may be configured. /// The which may be configured. /// The function delegate that creates a from the . Default is a GET request to the root URL ("/"). - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// A that represents the asynchronous operation. The task result contains the for the test server. public static async Task RunAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IWebHostFixture hostFixture = null) { @@ -63,7 +63,7 @@ public static async Task RunAsync(ActionThe which may be configured. /// The which may be configured. /// The function delegate that creates a from the . Default is a GET request to the root URL ("/"). - /// An optional implementation to use instead of the default instance. + /// An optional implementation to use instead of the default instance. /// A that represents the asynchronous operation. The task result contains the for the test server. public static async Task RunWithHostBuilderContextAsync(Action serviceSetup = null, Action pipelineSetup = null, Action hostSetup = null, Func> responseFactory = null, IWebHostFixture hostFixture = null) { From d760c0d8759669fed12c17f3fdfdb0b984fb46de Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:29:47 +0200 Subject: [PATCH 06/12] :building_construction: rename IMinimalWebHostFixture -> IWebMinimalHostFixture --- ...WebHostFixture.cs => IWebMinimalHostFixture.cs} | 2 +- .../Internal/MinimalWebHostTest.cs | 8 ++++---- .../MinimalWebHostTest.cs | 8 ++++---- ...sions.cs => WebMinimalHostFixtureExtensions.cs} | 14 +++++++------- 4 files changed, 16 insertions(+), 16 deletions(-) rename src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/{IMinimalWebHostFixture.cs => IWebMinimalHostFixture.cs} (88%) rename src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/{MinimalWebHostFixtureExtensions.cs => WebMinimalHostFixtureExtensions.cs} (58%) diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IMinimalWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IWebMinimalHostFixture.cs similarity index 88% rename from src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IMinimalWebHostFixture.cs rename to src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IWebMinimalHostFixture.cs index 79102b4..1845af0 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IMinimalWebHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IWebMinimalHostFixture.cs @@ -8,7 +8,7 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore /// /// /// - public interface IMinimalWebHostFixture : IMinimalHostFixture, IPipelineTest + public interface IWebMinimalHostFixture : IMinimalHostFixture, IPipelineTest { /// /// Gets or sets the delegate that configures the HTTP request pipeline. diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Internal/MinimalWebHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Internal/MinimalWebHostTest.cs index b7711f8..3c1dbbe 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Internal/MinimalWebHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/Internal/MinimalWebHostTest.cs @@ -5,7 +5,7 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore.Internal { - internal sealed class MinimalWebHostTest : MinimalWebHostTest + internal sealed class MinimalWebHostTest : MinimalWebHostTest { private readonly Action _pipelineConfigurator; private readonly Action _serviceConfigurator; @@ -14,7 +14,7 @@ internal sealed class MinimalWebHostTest : MinimalWebHostTest _hostConfigurator; private HostBuilderContext _hostBuilderContext; - internal MinimalWebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IMinimalWebHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal MinimalWebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IWebMinimalHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfigurator = serviceConfigurator; _pipelineConfigurator = pipelineConfigurator; @@ -22,7 +22,7 @@ internal MinimalWebHostTest(Action serviceConfigurator, Acti InitializeHostFixture(hostFixture); } - internal MinimalWebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IMinimalWebHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) + internal MinimalWebHostTest(Action serviceConfigurator, Action pipelineConfigurator, Action hostConfigurator, IWebMinimalHostFixture hostFixture) : base(true, hostFixture, callerType: pipelineConfigurator?.Target?.GetType() ?? serviceConfigurator?.Target?.GetType() ?? hostConfigurator?.Target?.GetType()) { _serviceConfiguratorWithContext = serviceConfigurator; _pipelineConfiguratorWithContext = pipelineConfigurator; @@ -30,7 +30,7 @@ internal MinimalWebHostTest(Action servi InitializeHostFixture(hostFixture); } - private void InitializeHostFixture(IMinimalWebHostFixture hostFixture) + private void InitializeHostFixture(IWebMinimalHostFixture hostFixture) { if (!hostFixture.HasValidState()) { diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs index 028591a..71668f2 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostTest.cs @@ -9,17 +9,17 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore /// /// Represents a base class from which all implementations of unit testing, that uses Microsoft Dependency Injection and depends on ASP.NET Core (minimal style), should derive. /// - /// The type of the object that implements the interface. + /// The type of the object that implements the interface. /// /// /// /// The class needed to be designed in this rather complex way, as this is the only way that xUnit supports a shared context. The need for shared context is theoretical at best, but it does opt-in for Scoped instances. - public abstract class MinimalWebHostTest : MinimalHostTest, IWebHostTest, IClassFixture where T : class, IMinimalWebHostFixture + public abstract class MinimalWebHostTest : MinimalHostTest, IWebHostTest, IClassFixture where T : class, IWebMinimalHostFixture { /// /// Initializes a new instance of the class. /// - /// An implementation of the interface. + /// An implementation of the interface. /// An implementation of the interface. /// The of caller that ends up invoking this instance. protected MinimalWebHostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : this(false, hostFixture, output, callerType) @@ -30,7 +30,7 @@ protected MinimalWebHostTest(T hostFixture, ITestOutputHelper output = null, Typ /// 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. /// An implementation of the interface. /// The of caller that ends up invoking this instance. /// diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixtureExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebMinimalHostFixtureExtensions.cs similarity index 58% rename from src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixtureExtensions.cs rename to src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebMinimalHostFixtureExtensions.cs index 110c191..ce03641 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/MinimalWebHostFixtureExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebMinimalHostFixtureExtensions.cs @@ -1,21 +1,21 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { /// - /// Extension methods for the interface. + /// Extension methods for the interface. /// - public static class MinimalWebHostFixtureExtensions + public static class WebMinimalHostFixtureExtensions { /// - /// Determines whether the specified has a valid state. + /// Determines whether the specified has a valid state. /// - /// The to check. - /// true if the specified has a valid state; otherwise, false. + /// The to check. + /// true if the specified has a valid state; otherwise, false. /// /// A valid state is defined as having non-null values for the following properties: /// , , - /// , and . + /// , and . /// - public static bool HasValidState(this IMinimalWebHostFixture hostFixture) + public static bool HasValidState(this IWebMinimalHostFixture hostFixture) { var hasValidState = ((IMinimalHostFixture)hostFixture).HasValidState(); return hasValidState && hostFixture.ConfigureApplicationCallback != null && hostFixture.Application != null; From 03d5adaec0bebabd0f3f06b17fa0be8b0f1ade87 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:30:12 +0200 Subject: [PATCH 07/12] :sparkles: added self-managed variants of managed web host fixtures --- .../SelfManagedWebHostFixture.cs | 21 +++++++++++++++++++ .../SelfManagedWebMinimalHostFixture.cs | 21 +++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebHostFixture.cs create mode 100644 src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebMinimalHostFixture.cs diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebHostFixture.cs new file mode 100644 index 0000000..0aa9818 --- /dev/null +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebHostFixture.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore +{ + /// + /// Represents a self-managed implementation of the class. + /// + public sealed class SelfManagedWebHostFixture : ManagedWebHostFixture + { + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor sets the to a no-op asynchronous delegate. + /// + public SelfManagedWebHostFixture() + { + AsyncHostRunnerCallback = (_, __) => Task.CompletedTask; + } + } +} diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebMinimalHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebMinimalHostFixture.cs new file mode 100644 index 0000000..6b94eb3 --- /dev/null +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/SelfManagedWebMinimalHostFixture.cs @@ -0,0 +1,21 @@ +using System.Threading.Tasks; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore +{ + /// + /// Represents a self-managed implementation of the class. + /// + public sealed class SelfManagedWebMinimalHostFixture : ManagedWebMinimalHostFixture + { + /// + /// Initializes a new instance of the class. + /// + /// + /// This constructor sets the to a no-op asynchronous delegate. + /// + public SelfManagedWebMinimalHostFixture() + { + AsyncHostRunnerCallback = (_, __) => Task.CompletedTask; + } + } +} From 377acfbcbf72bb4844590b459bd5a35b844eb210 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:31:54 +0200 Subject: [PATCH 08/12] :building_construction: rename BlockingWebHostFixture -> BlockingManagedWebHostFixture --- .../BlockingManagedWebHostFixture.cs | 24 +++++++++++++++++++ .../BlockingWebHostFixture.cs | 19 --------------- 2 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingManagedWebHostFixture.cs delete mode 100644 src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingWebHostFixture.cs diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingManagedWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingManagedWebHostFixture.cs new file mode 100644 index 0000000..d4b2c1b --- /dev/null +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingManagedWebHostFixture.cs @@ -0,0 +1,24 @@ +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore +{ + /// + /// Extends the default implementation of the interface to be synchronous e.g., blocking where exceptions can be captured. + /// + /// + public sealed class BlockingManagedWebHostFixture : ManagedWebHostFixture + { + /// + /// Initializes a new instance of the class. + /// + public BlockingManagedWebHostFixture() + { + AsyncHostRunnerCallback = (host, _) => + { + host.Start(); + return Task.CompletedTask; + }; + } + } +} diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingWebHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingWebHostFixture.cs deleted file mode 100644 index 8489d43..0000000 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/BlockingWebHostFixture.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Microsoft.Extensions.Hosting; - -namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore -{ - /// - /// Extends the default implementation of the interface to be synchronous e.g., blocking where exceptions can be captured. - /// - /// - public class BlockingWebHostFixture : WebHostFixture - { - /// - /// Initializes a new instance of the class. - /// - public BlockingWebHostFixture() - { - HostRunnerCallback = host => host.Run(); - } - } -} From ebad8fb96d17d18f044cbdeea02387b700a583ed Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 00:32:47 +0200 Subject: [PATCH 09/12] :white_check_mark: sync changes with unit tests --- .../Assets/ValidHostTest.cs | 4 ++-- ...FixtureTest.cs => ManagedWebHostFixtureTest.cs} | 14 +++++++------- .../MinimalMvcWebHostTestTest.cs | 6 +++--- .../MinimalWebHostTestTest.cs | 4 ++-- .../MvcWebHostTestTest.cs | 6 +++--- .../WebHostTestFactoryTest.cs | 2 +- .../WebHostTestTest.cs | 4 ++-- .../Assets/MinimalValidHostTest.cs | 4 ++-- .../Assets/ValidHostTest.cs | 4 ++-- .../HostTestTest.cs | 4 ++-- ...ostFixtureTest.cs => ManagedHostFixtureTest.cs} | 13 ++++++++----- .../MinimalHostFixtureTest.cs | 6 +++--- .../MinimalHostTestTest.cs | 4 ++-- 13 files changed, 39 insertions(+), 36 deletions(-) rename test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/{WebHostFixtureTest.cs => ManagedWebHostFixtureTest.cs} (77%) rename test/Codebelt.Extensions.Xunit.Hosting.Tests/{GenericHostFixtureTest.cs => ManagedHostFixtureTest.cs} (77%) 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 7b10a4a..548c5eb 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/ValidHostTest.cs @@ -3,9 +3,9 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore.Assets { - public class ValidHostTest : WebHostTest + public class ValidHostTest : WebHostTest { - public ValidHostTest(WebHostFixture hostFixture) : base(hostFixture) + public ValidHostTest(ManagedWebHostFixture hostFixture) : base(hostFixture) { } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostFixtureTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/ManagedWebHostFixtureTest.cs similarity index 77% rename from test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostFixtureTest.cs rename to test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/ManagedWebHostFixtureTest.cs index 8e63d94..3cfd8ce 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostFixtureTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/ManagedWebHostFixtureTest.cs @@ -6,9 +6,9 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { - public class WebHostFixtureTest : Test + public class ManagedWebHostFixtureTest : Test { - public WebHostFixtureTest(ITestOutputHelper output) : base(output) + public ManagedWebHostFixtureTest(ITestOutputHelper output) : base(output) { } @@ -16,7 +16,7 @@ public WebHostFixtureTest(ITestOutputHelper output) : base(output) public void ConfigureHost_NullHostTest_ThrowsArgumentNullException() { // Arrange - var fixture = new WebHostFixture(); + var fixture = new ManagedWebHostFixture(); // Act & Assert Assert.Throws(() => fixture.ConfigureHost(null)); @@ -26,8 +26,8 @@ public void ConfigureHost_NullHostTest_ThrowsArgumentNullException() public void ConfigureHost_InvalidHostTestType_ThrowsArgumentOutOfRangeException() { // Arrange - var fixture = new WebHostFixture(); - var invalidHostTest = new InvalidHostTest(fixture); + var fixture = new ManagedWebHostFixture(); + var invalidHostTest = new InvalidHostTest(fixture); // Act & Assert Assert.Throws(() => fixture.ConfigureHost(invalidHostTest)); @@ -37,7 +37,7 @@ public void ConfigureHost_InvalidHostTestType_ThrowsArgumentOutOfRangeException( public void ConfigureApplicationCallback_SetAndGet_ReturnsCorrectValue() { // Arrange - var fixture = new WebHostFixture(); + var fixture = new ManagedWebHostFixture(); Action callback = app => { }; // Act @@ -51,7 +51,7 @@ public void ConfigureApplicationCallback_SetAndGet_ReturnsCorrectValue() public void ConfigureHost_ValidHostTest_ConfiguresHostCorrectly() { // Arrange - var fixture = new WebHostFixture(); + var fixture = new ManagedWebHostFixture(); var hostTest = new ValidHostTest(fixture); // Act diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalMvcWebHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalMvcWebHostTestTest.cs index 268ec93..da70668 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalMvcWebHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalMvcWebHostTestTest.cs @@ -11,12 +11,12 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { - public class MinimalMvcWebHostTestTest : MinimalWebHostTest + public class MinimalMvcWebHostTestTest : MinimalWebHostTest { - private readonly MinimalWebHostFixture _hostFixture; + private readonly ManagedWebMinimalHostFixture _hostFixture; private readonly HttpClient _client; - public MinimalMvcWebHostTestTest(MinimalWebHostFixture hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) + public MinimalMvcWebHostTestTest(ManagedWebMinimalHostFixture hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) { hostFixture.Host.Services.GetRequiredService().TestOutput = output; _hostFixture = hostFixture; diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalWebHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalWebHostTestTest.cs index 792a2ab..bf9159a 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalWebHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MinimalWebHostTestTest.cs @@ -15,12 +15,12 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { - public class MinimalWebHostTestTest : MinimalWebHostTest + public class MinimalWebHostTestTest : MinimalWebHostTest { private readonly IServiceProvider _provider; private readonly IApplicationBuilder _pipeline; - public MinimalWebHostTestTest(MinimalWebHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) + public MinimalWebHostTestTest(ManagedWebMinimalHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { _pipeline = hostFixture.Application; _provider = hostFixture.Host.Services; diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcWebHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcWebHostTestTest.cs index e5d51b6..7767bb9 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcWebHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcWebHostTestTest.cs @@ -10,12 +10,12 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { - public class MvcWebHostTestTest : WebHostTest + public class MvcWebHostTestTest : WebHostTest { - private readonly WebHostFixture _hostFixture; + private readonly ManagedWebHostFixture _hostFixture; private readonly HttpClient _client; - public MvcWebHostTestTest(WebHostFixture hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) + public MvcWebHostTestTest(ManagedWebHostFixture hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) { hostFixture.Host.Services.GetRequiredService().TestOutput = output; _hostFixture = hostFixture; diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs index 79a122c..cd22af3 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs @@ -47,7 +47,7 @@ public void Create_ShouldThrowSecurityException_DueToBlockingAspNetCoreHostFixtu o.ValidateScopes = false; }); }, - new BlockingWebHostFixture())); + new BlockingManagedWebHostFixture())); } [Fact] diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestTest.cs index d2211d1..864f876 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestTest.cs @@ -14,12 +14,12 @@ namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore { - public class WebHostTestTest : WebHostTest + public class WebHostTestTest : WebHostTest { private readonly IServiceProvider _provider; private readonly IApplicationBuilder _pipeline; - public WebHostTestTest(WebHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) + public WebHostTestTest(ManagedWebHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { _pipeline = hostFixture.Application; _provider = hostFixture.Host.Services; diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/MinimalValidHostTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/MinimalValidHostTest.cs index 6f8a6ce..c28f88b 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/MinimalValidHostTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/MinimalValidHostTest.cs @@ -4,9 +4,9 @@ namespace Codebelt.Extensions.Xunit.Hosting.Assets { - public class MinimalValidHostTest : MinimalHostTest + public class MinimalValidHostTest : MinimalHostTest { - public MinimalValidHostTest(MinimalHostFixture hostFixture) : base(hostFixture) + public MinimalValidHostTest(ManagedMinimalHostFixture hostFixture) : base(hostFixture) { } } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs index cc58dd5..29d398c 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/Assets/ValidHostTest.cs @@ -5,9 +5,9 @@ namespace Codebelt.Extensions.Xunit.Hosting.Assets { - public class ValidHostTest : HostTest + public class ValidHostTest : HostTest { - public ValidHostTest(GenericHostFixture hostFixture) : base(hostFixture) + public ValidHostTest(ManagedHostFixture hostFixture) : base(hostFixture) { } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs index 76db11f..a31fff1 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/HostTestTest.cs @@ -13,14 +13,14 @@ namespace Codebelt.Extensions.Xunit.Hosting { [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] - public class HostTestTest : HostTest + public class HostTestTest : HostTest { private bool _isHostRunning = false; private readonly IServiceScope _scope; private readonly Func> _correlationsFactory; private static readonly ConcurrentBag ScopedCorrelations = new(); - public HostTestTest(GenericHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) + public HostTestTest(ManagedHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { _scope = hostFixture.Host.Services.CreateScope(); _correlationsFactory = () => _scope.ServiceProvider.GetServices().ToList(); diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostFixtureTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/ManagedHostFixtureTest.cs similarity index 77% rename from test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostFixtureTest.cs rename to test/Codebelt.Extensions.Xunit.Hosting.Tests/ManagedHostFixtureTest.cs index a6aea23..fe94927 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/GenericHostFixtureTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/ManagedHostFixtureTest.cs @@ -1,18 +1,21 @@ using System; using System.Threading.Tasks; using Codebelt.Extensions.Xunit.Hosting.Assets; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; using Xunit; using Xunit.Abstractions; namespace Codebelt.Extensions.Xunit.Hosting { - public class GenericHostFixtureTest : Test + public class ManagedHostFixtureTest : Test { - private readonly GenericHostFixture _hostFixture; + private readonly ManagedHostFixture _hostFixture; - public GenericHostFixtureTest(ITestOutputHelper output) : base(output) + public ManagedHostFixtureTest(ITestOutputHelper output) : base(output) { - _hostFixture = new GenericHostFixture(); + _hostFixture = new ManagedHostFixture(); } [Fact] @@ -24,7 +27,7 @@ public void ConfigureHost_ShouldThrowArgumentNullException_WhenHostTestIsNull() [Fact] public void ConfigureHost_ShouldThrowArgumentOutOfRangeException_WhenHostTestIsNotAssignableFromHostTest() { - var invalidHostTest = new InvalidHostTest(new GenericHostFixture()); + var invalidHostTest = new InvalidHostTest(new ManagedHostFixture()); Assert.Throws(() => _hostFixture.ConfigureHost(invalidHostTest)); } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostFixtureTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostFixtureTest.cs index 7514f65..f9c223c 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostFixtureTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostFixtureTest.cs @@ -8,11 +8,11 @@ namespace Codebelt.Extensions.Xunit.Hosting { public class MinimalHostFixtureTest : Test { - private readonly MinimalHostFixture _hostFixture; + private readonly ManagedMinimalHostFixture _hostFixture; public MinimalHostFixtureTest(ITestOutputHelper output) : base(output) { - _hostFixture = new MinimalHostFixture(); + _hostFixture = new ManagedMinimalHostFixture(); } [Fact] @@ -24,7 +24,7 @@ public void ConfigureHost_ShouldThrowArgumentNullException_WhenHostTestIsNull() [Fact] public void ConfigureHost_ShouldThrowArgumentOutOfRangeException_WhenHostTestIsNotAssignableFromHostTest() { - var invalidHostTest = new InvalidHostTest(new GenericHostFixture()); + var invalidHostTest = new InvalidHostTest(new ManagedHostFixture()); Assert.Throws(() => _hostFixture.ConfigureHost(invalidHostTest)); } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostTestTest.cs index 8a19085..e1df5f3 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.Tests/MinimalHostTestTest.cs @@ -13,14 +13,14 @@ namespace Codebelt.Extensions.Xunit.Hosting { [TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)] - public class MinimalHostTestTest : MinimalHostTest + public class MinimalHostTestTest : MinimalHostTest { private bool _isHostRunning = false; private readonly IServiceScope _scope; private readonly Func> _correlationsFactory; private static readonly ConcurrentBag ScopedCorrelations = new(); - public MinimalHostTestTest(MinimalHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) + public MinimalHostTestTest(ManagedMinimalHostFixture hostFixture, ITestOutputHelper output) : base(hostFixture, output) { _scope = hostFixture.Host.Services.CreateScope(); _correlationsFactory = () => _scope.ServiceProvider.GetServices().ToList(); From 63db42d1c3edadb6fe66437c69f08c762b5f4d60 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 02:10:07 +0200 Subject: [PATCH 10/12] :arrow_up: bump dependencies --- Directory.Packages.props | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index f94a664..4771655 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -4,9 +4,9 @@ true - - - + + + From 62e245bfa91a6d8360a622156123c4fb56040e70 Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 02:11:49 +0200 Subject: [PATCH 11/12] :package: updated NuGet package definition --- .../PackageReleaseNotes.txt | 12 +++++++----- .../PackageReleaseNotes.txt | 8 +++++--- .../PackageReleaseNotes.txt | 3 +++ 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt index 24c7365..f54b79a 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt @@ -5,20 +5,22 @@ Availability: .NET 9 and .NET 8 - CHANGED Dependencies to latest and greatest with respect to TFMs   # Breaking Changes -- RENAMED AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to WebHostFixture +- RENAMED AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to ManagedWebHostFixture - REMOVED AspNetCoreHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace - RENAMED AspNetCoreHostTest class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to WebHostTest -- RENAMED BlockingAspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to BlockingWebHostFixture +- RENAMED BlockingAspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to BlockingManagedWebHostFixture - RENAMED IAspNetCoreHostFixture interface in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to IWebHostFixture   # New Features - ADDED WebHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IWebHostFixture interface: HasValidState - ADDED HostBuilderApplicationExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IHostApplicationBuilder interface: ToHostBuilder -- ADDED IMinimalWebHostFixture interface in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a way to use Microsoft Dependency Injection in unit tests (minimal style) -- ADDED MinimalWebHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a default implementation of the IMinimalWebHostFixture interface -- ADDED MinimalWebHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IMinimalWebHostFixture interface: HasValidState +- ADDED IWebMinimalHostFixture interface in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a way to use Microsoft Dependency Injection in unit tests (minimal style) +- ADDED ManagedWebMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a default implementation of the IWebMinimalHostFixture interface +- ADDED WebMinimalHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IWebMinimalHostFixture interface: HasValidState - ADDED MinimalWebHostTest{T} class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that represents a base class from which all implementations of unit testing, that uses Microsoft Dependency Injection and depends on ASP.NET Core (minimal style), should derive - ADDED MinimalWebHostTestFactory class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a set of static methods for ASP.NET Core (minimal style) unit testing +- ADDED SelfManagedWebHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a self-managed implementation of the ManagedWebHostFixture class (i.e., the host is not started automatically) +- ADDED SelfManagedWebMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a self-managed implementation of the ManagedWebMinimalHostFixture class (i.e., the host is not started automatically)   Version 9.1.3 Availability: .NET 9 and .NET 8 diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt index 5494919..ea05487 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt @@ -9,21 +9,23 @@ Availability: .NET 9, .NET 8 and .NET Standard 2.0 - RENAMED GenericHostTestFactory in the Codebelt.Extensions.Xunit.Hosting namespace to HostTestFactory - RENAMED IGenericHostTest in the Codebelt.Extensions.Xunit.Hosting namespace to IHostTest - REMOVED IServiceTest interface in the Codebelt.Extensions.Xunit.Hosting namespace due to redundancies with the IHost interface (Services property) -- CHANGED HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace to an abstract class from which all other host fixture classes derive from (e.g., WebHostFixture, GenericHostFixture, etc.) +- CHANGED HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace to an abstract class from which all other host fixture classes derive from (e.g., ManagedWebHostFixture, ManagedHostFixture, etc.) - REMOVED HostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace - CHANGED IHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace to be more confined in scope (e.g., less interface inheritance and ultimately fewer members)   # New Features - ADDED HostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalHostTest{T}, HostTest{T}, etc.) - ADDED IGenericHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host -- ADDED GenericHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IGenericHostFixture interface (replaces the legacy HostFixture class) +- ADDED ManagedHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IGenericHostFixture interface (replaces the legacy HostFixture class) - ADDED GenericHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IGenericHostFixture interface: HasValidState - ADDED IMinimalHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host (minimal style) -- ADDED MinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IMinimalHostFixture interface +- ADDED ManagedMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IMinimalHostFixture interface - ADDED MinimalHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IMinimalHostFixture interface: HasValidState - ADDED MinimalHostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalWebHostTest, {T}, MinimalHostTest{T}, etc.) - ADDED MinimalHostTestFactory class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of static methods for IHost unit testing (minimal style) - EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with one new extension method for the IServiceCollection interface: An overload of AddXunitTestLogging that does not rely on the ITestOutputHelper interface +- ADDED SelfManagedHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that represents a self-managed implementation of the ManagedHostFixture class (i.e., the host is not started automatically) +- ADDED SelfManagedMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that represents a self-managed implementation of the ManagedMinimalHostFixture class (i.e., the host is not started automatically)   Version 9.1.3 Availability: .NET 9, .NET 8 and .NET Standard 2.0 diff --git a/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt index 3a769c1..d7cee4d 100644 --- a/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit/PackageReleaseNotes.txt @@ -4,6 +4,9 @@ Availability: .NET 9 and .NET 8 # ALM - CHANGED Dependencies to latest and greatest with respect to TFMs   +# Improvements +- EXTENDED Test class in the Codebelt.Extensions.Xunit namespace to report unhandled exceptions in the test output using the injected ITestOutputHelper interface +  Version 9.1.3 Availability: .NET 9 and .NET 8   From 8fc886b9302b526bd6e460c5ec2625310fcd7b5d Mon Sep 17 00:00:00 2001 From: Michael Mortensen Date: Sat, 12 Apr 2025 02:12:38 +0200 Subject: [PATCH 12/12] :speech_balloon: updated community health pages --- CHANGELOG.md | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 649f0bc..ae88606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,35 +15,38 @@ This major release introduces support for unit testing Minimal APIs and includes - HostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalHostTest{T}, HostTest{T}, etc.) - IGenericHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host -- GenericHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IGenericHostFixture interface (replaces the legacy HostFixture class) +- ManagedHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IGenericHostFixture interface (replaces the legacy HostFixture class) - GenericHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IGenericHostFixture interface: HasValidState - IMinimalHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host (minimal style) -- MinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IMinimalHostFixture interface -- MinimalHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IMinimalHostFixture interface: HasValidState -- MinimalHostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalWebHostTest, {T}, MinimalHostTest{T}, etc.) -- MinimalHostTestFactory class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of static methods for IHost unit testing (minimal style) -- HostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalHostTest{T}, HostTest{T}, etc.) -- IGenericHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host -- GenericHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IGenericHostFixture interface -- GenericHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IGenericHostFixture interface: HasValidState -- IMinimalHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of members for configuring the host (minimal style) -- MinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IMinimalHostFixture interface +- ManagedMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a default implementation of the IMinimalHostFixture interface - MinimalHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IMinimalHostFixture interface: HasValidState - MinimalHostTest class in the Codebelt.Extensions.Xunit.Hosting namespace that represents the non-generic base class from where its generic equivalent should derive (e.g., MinimalWebHostTest, {T}, MinimalHostTest{T}, etc.) - MinimalHostTestFactory class in the Codebelt.Extensions.Xunit.Hosting namespace that provides a set of static methods for IHost unit testing (minimal style) - ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace received one new extension method for the IServiceCollection interface: An overload of AddXunitTestLogging that does not rely on the ITestOutputHelper interface - This was done to help mitigate those scenarios where the [current design of xUnit v2 and ITestOutputHelper can cause deadlocks](https://github.com/xunit/xunit/discussions/2994), e.g. you can access the xUnit logger but nothing is logged to the test output +- WebHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IWebHostFixture interface: HasValidState +- HostBuilderApplicationExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IHostApplicationBuilder interface: ToHostBuilder +- IWebMinimalHostFixture interface in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a way to use Microsoft Dependency Injection in unit tests (minimal style) +- ManagedWebMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a default implementation of the IWebMinimalHostFixture interface +- WebMinimalHostFixtureExtensions class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that consist of one extension method for the IWebMinimalHostFixture interface: HasValidState +- MinimalWebHostTest{T} class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that represents a base class from which all implementations of unit testing, that uses Microsoft Dependency Injection and depends on ASP.NET Core (minimal style), should derive +- MinimalWebHostTestFactory class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a set of static methods for ASP.NET Core (minimal style) unit testing +- SelfManagedHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that represents a self-managed implementation of the ManagedHostFixture class (i.e., the host is not started automatically) +- SelfManagedMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace that represents a self-managed implementation of the ManagedMinimalHostFixture class (i.e., the host is not started automatically) +- SelfManagedWebHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a self-managed implementation of the ManagedWebHostFixture class (i.e., the host is not started automatically) +- SelfManagedWebMinimalHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace that provides a self-managed implementation of the ManagedWebMinimalHostFixture class (i.e., the host is not started automatically) ### Changed +- Test class in the Codebelt.Extensions.Xunit namespace to report unhandled exceptions in the test output using the injected ITestOutputHelper interface - IHostingEnvironmentTest in the Codebelt.Extensions.Xunit.Hosting namespace was renamed to IEnvironmentTest (breaking change) - GenericHostTestFactory in the Codebelt.Extensions.Xunit.Hosting namespace was renamed to HostTestFactory (breaking change) - IGenericHostTest in the Codebelt.Extensions.Xunit.Hosting namespace was renamed to IHostTest (breaking change) -- HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace was changed to an abstract class from which all other host fixture classes derive from (e.g., WebHostFixture, GenericHostFixture, etc.) +- HostFixture class in the Codebelt.Extensions.Xunit.Hosting namespace was changed to an abstract class from which all other host fixture classes derive from (e.g., ManagedWebHostFixture, ManagedHostFixture, etc.) - IHostFixture interface in the Codebelt.Extensions.Xunit.Hosting namespace was changed to be more confined in scope (e.g., less interface inheritance and ultimately fewer members) -- AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to WebHostFixture (breaking change) +- AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to ManagedWebHostFixture (breaking change) - AspNetCoreHostTest class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to WebHostTest (breaking change) -- BlockingAspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to BlockingWebHostFixture (breaking change) +- BlockingAspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to BlockingManagedWebHostFixture (breaking change) - IAspNetCoreHostFixture interface in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace was renamed to IWebHostFixture (breaking change) ### Removed