diff --git a/.nuget/Codebelt.Extensions.Xunit.App/README.md b/.nuget/Codebelt.Extensions.Xunit.App/README.md index 9b8dfea..8d853f1 100644 --- a/.nuget/Codebelt.Extensions.Xunit.App/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.App/README.md @@ -1,6 +1,7 @@ ## About -An open-source project (MIT license) that targets and complements the [xUnit.net](https://xunit.net/) test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. + It is, by heart, free, flexible and built to extend and boost your agile codebelt. ## **Codebelt.Extensions.Xunit.App** for .NET diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt index 010b1d2..2a299f2 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/PackageReleaseNotes.txt @@ -5,6 +5,9 @@ Availability: .NET 9 and .NET 8 - CHANGED Dependencies to latest and greatest with respect to TFMs - REMOVED Support for TFM .NET 6 (LTS)   +# Bug Fixes +- FIXED AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to preserve ExecutionContext and AsyncLocal{T} values from the client to the server (vital for ITestOutputHelperAccessor combined with xUnit test logging when using HttpClient) +  Version 8.4.0 Availability: .NET 8 and .NET 6   diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md index 181ce62..4471b45 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting.AspNetCore/README.md @@ -1,6 +1,9 @@ ## About -An open-source project (MIT license) that targets and complements the [xUnit.net](https://xunit.net/) test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. + +Perhaps even more convenient than what [WebApplicationFactory](https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.testing.webapplicationfactory-1) has to offer? + It is, by heart, free, flexible and built to extend and boost your agile codebelt. ## **Codebelt.Extensions.Xunit.Hosting.AspNetCore** for .NET diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt index c016419..4f1d19e 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/PackageReleaseNotes.txt @@ -5,6 +5,18 @@ Availability: .NET 9, .NET 8 and .NET Standard 2.0 - CHANGED Dependencies to latest and greatest with respect to TFMs - REMOVED Support for TFM .NET 6 (LTS)   +Version 8.4.1 +Availability: .NET 8, .NET 6 and .NET Standard 2.0 +  +# ALM +- CHANGED Dependencies to latest and greatest with respect to TFMs +  +# Breaking Changes +- RENAMED AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} on the ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace to AddXunitTestLoggingOutputHelperAccessor and AddXunitTestLoggingOutputHelperAccessor{T} (for consistency) +  +# New Features +- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with one new extension method for the IServiceCollection interface: An overload of AddXunitTestLogging +  Version 8.4.0 Availability: .NET 8, .NET 6 and .NET Standard 2.0   @@ -13,7 +25,7 @@ Availability: .NET 8, .NET 6 and .NET Standard 2.0   # New Features - ADDED ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService -- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} +- EXTENDED ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace with two new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T}   Version 8.3.2 Availability: .NET 8, .NET 6 and .NET Standard 2.0 diff --git a/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md b/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md index 44db448..1d01b65 100644 --- a/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md +++ b/.nuget/Codebelt.Extensions.Xunit.Hosting/README.md @@ -1,6 +1,7 @@ ## About -An open-source project (MIT license) that targets and complements the [xUnit.net](https://xunit.net/) test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. + It is, by heart, free, flexible and built to extend and boost your agile codebelt. ## **Codebelt.Extensions.Xunit.Hosting** for .NET @@ -37,7 +38,7 @@ public class AspNetCoreHostTestTest : AspNetCoreHostTest public override void ConfigureServices(IServiceCollection services) { - services.AddXunitTestOutputHelperAccessor(); + services.AddXunitTestLoggingOutputHelperAccessor(); services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput)); } } diff --git a/.nuget/Codebelt.Extensions.Xunit/README.md b/.nuget/Codebelt.Extensions.Xunit/README.md index c55469d..184b70a 100644 --- a/.nuget/Codebelt.Extensions.Xunit/README.md +++ b/.nuget/Codebelt.Extensions.Xunit/README.md @@ -1,6 +1,7 @@ ## About -An open-source project (MIT license) that targets and complements the [xUnit.net](https://xunit.net/) test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. +An open-source project (MIT license) that targets and complements the xUnit.net test platform. It provides a uniform and convenient way of doing unit test for all project types in .NET. + It is, by heart, free, flexible and built to extend and boost your agile codebelt. ## **Codebelt.Extensions.Xunit** for .NET diff --git a/CHANGELOG.md b/CHANGELOG.md index f30a27b..15399c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,27 @@ For more details, please refer to `PackageReleaseNotes.txt` on a per assembly ba This major release is first and foremost focused on ironing out any wrinkles that have been introduced with .NET 9 preview releases so the final release is production ready together with the official launch from Microsoft. +### Fixed + +- AspNetCoreHostFixture class in the Codebelt.Extensions.Xunit.Hosting.AspNetCore namespace to preserve ExecutionContext and AsyncLocal{T} values from the client to the server (vital for ITestOutputHelperAccessor combined with xUnit test logging when using HttpClient) + - Prior to this release, you can override `ConfigureHost` on your `AspNetCoreHostTest` implementation and apply this code: + ```csharp + protected override void ConfigureHost(IHostBuilder hb) + { + hb.ConfigureWebHost(builder => builder.UseTestServer(o => o.PreserveExecutionContext = true)); + } + ``` + +## [8.4.1] - 2024-09-16 + +### Added + +- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace received one new extension method for the IServiceCollection interface: An overload of AddXunitTestLogging + +### Changed + +- AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} on the ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was renamed to AddXunitTestLoggingOutputHelperAccessor and AddXunitTestLoggingOutputHelperAccessor{T} (for consistency) + ## [8.4.0] - 2024-09-15 ### Added @@ -19,7 +40,7 @@ This major release is first and foremost focused on ironing out any wrinkles tha - ITestOutputHelperAccessor interface in the Codebelt.Extensions.Xunit namespace that provides access to the ITestOutputHelper instance - TestOutputHelperAccessor class in the Codebelt.Extensions.Xunit namespace that provides a default implementation of the ITestOutputHelper interface - ServiceProviderExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace that consist of one extension method for the IServiceProvider interface: GetRequiredScopedService -- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace was extended with three new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} +- ServiceCollectionExtensions class in the Codebelt.Extensions.Xunit.Hosting namespace received two new extension methods for the IServiceCollection interface: AddXunitTestOutputHelperAccessor and AddXunitTestOutputHelperAccessor{T} ### Changed diff --git a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs index 2f21154..07a9495 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/AspNetCoreHostFixture.cs @@ -47,7 +47,7 @@ public override void ConfigureHost(Test hostTest) .ConfigureWebHost(webBuilder => { webBuilder - .UseTestServer() + .UseTestServer(o => o.PreserveExecutionContext = true) .UseContentRoot(Directory.GetCurrentDirectory()) .UseEnvironment("Development") .ConfigureAppConfiguration((context, config) => @@ -82,16 +82,19 @@ public override void ConfigureHost(Test hostTest) .UseSetting(HostDefaults.ApplicationKey, hostTest.CallerType.Assembly.GetName().Name); }); - ConfigureHostCallback(hb); - hb.UseDefaultServiceProvider(o => { o.ValidateOnBuild = true; o.ValidateScopes = true; }); + ConfigureHostCallback(hb); + var host = hb.Build(); - Task.Run(() => host.StartAsync()).GetAwaiter().GetResult(); + Task.Run(() => host.StartAsync().ConfigureAwait(false)) + .ConfigureAwait(false) + .GetAwaiter() + .GetResult(); Host = host; } diff --git a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs index 90943b9..7a7e13b 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/LoggerExtensions.cs @@ -2,7 +2,9 @@ using System.Collections; using System.Linq; using Cuemon; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Xunit.Abstractions; namespace Codebelt.Extensions.Xunit.Hosting { @@ -12,7 +14,7 @@ namespace Codebelt.Extensions.Xunit.Hosting public static class LoggerExtensions { /// - /// Returns the associated that is provided when settings up services from . + /// Returns the associated that is provided when settings up services from either or . /// /// The from which to retrieve the . /// Returns an implementation of with all logged entries expressed as . diff --git a/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs b/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs index 328c5da..f935e08 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/ServiceCollectionExtensions.cs @@ -11,37 +11,60 @@ namespace Codebelt.Extensions.Xunit.Hosting /// public static class ServiceCollectionExtensions { - /// - /// Adds a unit test optimized implementation of output logging to the collection. - /// - /// The to extend. - /// The that provides the output for the logging. - /// The that specifies the minimum level to include for the logging. - /// A reference to so that additional configuration calls can be chained. - /// - /// cannot be null -or- - /// cannot be null. - /// - public static IServiceCollection AddXunitTestLogging(this IServiceCollection services, ITestOutputHelper output, LogLevel minimumLevel = LogLevel.Trace) - { - Validator.ThrowIfNull(services); - Validator.ThrowIfNull(output); - services.AddLogging(builder => - { - builder.SetMinimumLevel(minimumLevel); - builder.AddProvider(new XunitTestLoggerProvider(output)); - }); - return services; - } + /// + /// Adds a unit test optimized implementation of output logging to the collection. + /// + /// The to extend. + /// The that provides the output for the logging. + /// The that specifies the minimum level to include for the logging. + /// A reference to so that additional configuration calls can be chained. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static IServiceCollection AddXunitTestLogging(this IServiceCollection services, ITestOutputHelper output, LogLevel minimumLevel = LogLevel.Trace) + { + Validator.ThrowIfNull(services); + Validator.ThrowIfNull(output); + services.AddLogging(builder => + { + builder.SetMinimumLevel(minimumLevel); + builder.AddProvider(new XunitTestLoggerProvider(output)); + }); + return services; + } + /// + /// Adds a unit test optimized implementation of output logging to the collection. + /// + /// The to extend. + /// The that provides access to the output for the logging. + /// The that specifies the minimum level to include for the logging. + /// A reference to so that additional configuration calls can be chained. + /// + /// cannot be null -or- + /// cannot be null. + /// + public static IServiceCollection AddXunitTestLogging(this IServiceCollection services, ITestOutputHelperAccessor accessor, LogLevel minimumLevel = LogLevel.Trace) + { + Validator.ThrowIfNull(services); + Validator.ThrowIfNull(accessor); + services.AddLogging(builder => + { + builder.SetMinimumLevel(minimumLevel); + builder.AddProvider(new XunitTestLoggerProvider(accessor)); + }); + return services; + } + /// /// Adds a default implementation of to the collection. /// /// The to extend. /// A reference to so that additional configuration calls can be chained. - public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceCollection services) + public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor(this IServiceCollection services) { - services.AddXunitTestOutputHelperAccessor(); + services.AddXunitTestLoggingOutputHelperAccessor(); return services; } @@ -54,7 +77,7 @@ public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceC /// /// cannot be null. /// - public static IServiceCollection AddXunitTestOutputHelperAccessor(this IServiceCollection services) where T : class, ITestOutputHelperAccessor + public static IServiceCollection AddXunitTestLoggingOutputHelperAccessor(this IServiceCollection services) where T : class, ITestOutputHelperAccessor { Validator.ThrowIfNull(services); services.AddSingleton(); diff --git a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs index e183a06..e9a317d 100644 --- a/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs +++ b/src/Codebelt.Extensions.Xunit.Hosting/XunitTestLogger.cs @@ -28,6 +28,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except var message = builder.ToString(); if (_accessor != null) { + if (_accessor.TestOutput == null) { throw new InvalidOperationException($"{nameof(ITestOutputHelperAccessor)}.{nameof(ITestOutputHelperAccessor.TestOutput)} is null."); } _accessor.TestOutput.WriteLine(message); } else diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs index 296dca2..de7e2cf 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/AspNetCoreHostTestTest.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using Codebelt.Extensions.Xunit.Hosting.AspNetCore.Assets; using Codebelt.Extensions.Xunit.Hosting.AspNetCore.Http; @@ -34,6 +35,9 @@ public async Task ShouldHaveResultOfBoolMiddlewareInBody() Assert.Equal("Hello awesome developers!", context!.Response.Body.ToEncodedString(o => o.LeaveOpen = true)); + var logger = _pipeline.ApplicationServices.GetRequiredService>(); + logger.LogInformation("Hello from {0}", nameof(ShouldHaveResultOfBoolMiddlewareInBody)); + await pipeline(context); Assert.Equal("A:True, B:False, C:True, D:False, E:True, F:False", context.Response.Body.ToEncodedString()); @@ -51,6 +55,11 @@ public void ShouldLogToXunitTestLogging() { var logger = _pipeline.ApplicationServices.GetRequiredService>(); logger.LogInformation("Hello from {0}", nameof(ShouldLogToXunitTestLogging)); + var store = _pipeline.ApplicationServices.GetRequiredService>().GetTestStore(); + var entry = store.Query(entry => entry.Message.Contains("Hello from", StringComparison.OrdinalIgnoreCase)).SingleOrDefault(); + + Assert.NotNull(entry); + Assert.Equal("Information: Hello from ShouldLogToXunitTestLogging", entry.Message); } public override void ConfigureApplication(IApplicationBuilder app) @@ -68,8 +77,8 @@ public override void ConfigureServices(IServiceCollection services) o.C = true; o.E = true; }); - services.AddXunitTestOutputHelperAccessor(); - services.AddXunitTestLogging(TestOutput); + services.AddXunitTestLoggingOutputHelperAccessor(); + services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput)); } } } diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/FakeController.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/FakeController.cs new file mode 100644 index 0000000..e27552b --- /dev/null +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Assets/FakeController.cs @@ -0,0 +1,19 @@ +using Microsoft.AspNetCore.Mvc; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore.Assets +{ + [ApiController] + [Route("[controller]")] + public class FakeController : ControllerBase + { + public FakeController() + { + } + + [HttpGet] + public IActionResult Get() + { + return Ok("Unit Test"); + } + } +} diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj index 1ac5eb6..910a26b 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests.csproj @@ -7,6 +7,7 @@ + diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs new file mode 100644 index 0000000..ed459e5 --- /dev/null +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/MvcAspNetCoreHostTestTest.cs @@ -0,0 +1,58 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Codebelt.Extensions.Xunit.Hosting.AspNetCore.Assets; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using Xunit; +using Xunit.Abstractions; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore +{ + public class MvcAspNetCoreHostTestTest : AspNetCoreHostTest + { + private readonly AspNetCoreHostFixture _hostFixture; + private readonly HttpClient _client; + + public MvcAspNetCoreHostTestTest(AspNetCoreHostFixture hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(hostFixture, output, callerType) + { + hostFixture.ServiceProvider.GetRequiredService().TestOutput = output; + _hostFixture = hostFixture; + _client = hostFixture.Host.GetTestClient(); + } + + [Fact] + public async Task GetTestAsync() + { + var response = await _client.GetAsync("/Fake"); + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + Assert.Equal("Unit Test", body); + } + + [Fact] + public async Task GetTestAsync2() + { + var response = await _client.GetAsync("/Fake"); + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + Assert.Equal("Unit Test", body); + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddControllers() + .AddApplicationPart(typeof(FakeController).Assembly); + + services.AddXunitTestLoggingOutputHelperAccessor(); + services.AddXunitTestLogging(new TestOutputHelperAccessor(TestOutput)); + } + + public override void ConfigureApplication(IApplicationBuilder app) + { + app.UseRouting(); + app.UseEndpoints(routes => { routes.MapControllers(); }); + } + } +} diff --git a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs index 1cec236..2ebc78a 100644 --- a/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs +++ b/test/Codebelt.Extensions.Xunit.Hosting.AspNetCore.Tests/WebHostTestFactoryTest.cs @@ -1,73 +1,114 @@ -using System; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore -{ - public class WebHostTestFactoryTest : Test - { - public WebHostTestFactoryTest(ITestOutputHelper output) : base(output) - { - } - - [Fact] - public void CreateMiddlewareTest_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest() - { - Type sut1 = GetType(); - string sut2 = null; - var middleware = WebHostTestFactory.Create(Assert.NotNull, Assert.NotNull, host => - { - host.ConfigureAppConfiguration((context, configuration) => - { - sut2 = context.HostingEnvironment.ApplicationName; - }); - }); - - Assert.True(sut1 == middleware.CallerType.DeclaringType); - Assert.Equal(GetType().Assembly.GetName().Name, sut2); - } - - [Fact] - public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly() - { - return WebHostTestFactory.RunAsync(Assert.NotNull, Assert.NotNull, host => - { - host.ConfigureAppConfiguration((context, configuration) => - { - TestOutput.WriteLine(context.HostingEnvironment.ApplicationName); - Assert.Equal(GetType().Assembly.GetName().Name, context.HostingEnvironment.ApplicationName); - }); - }); - } - - [Fact] - public Task RunMiddlewareTest_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext() - { - return WebHostTestFactory.RunWithHostBuilderContextAsync((context, app) => - { - Assert.NotNull(context); - Assert.NotNull(context.HostingEnvironment); - Assert.NotNull(context.Configuration); - Assert.NotNull(context.Properties); - Assert.NotNull(app); - }, - (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); - }); - }); - } - } -} +using System; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Cuemon.AspNetCore.Diagnostics; +using Cuemon.Extensions.AspNetCore.Diagnostics; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Xunit; +using Xunit.Abstractions; + +namespace Codebelt.Extensions.Xunit.Hosting.AspNetCore +{ + public class WebHostTestFactoryTest : Test + { + public WebHostTestFactoryTest(ITestOutputHelper output) : base(output) + { + } + + [Fact] + public void Create_CallerTypeShouldHaveDeclaringTypeOfMiddlewareTestFactoryTest() + { + Type sut1 = GetType(); + string sut2 = null; + var middleware = WebHostTestFactory.Create(Assert.NotNull, 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 Task RunAsync_ShouldHaveApplicationNameEqualToThisAssembly() + { + return WebHostTestFactory.RunAsync(Assert.NotNull, Assert.NotNull, host => + { + host.ConfigureAppConfiguration((context, _) => + { + TestOutput.WriteLine(context.HostingEnvironment.ApplicationName); + Assert.Equal(GetType().Assembly.GetName().Name, context.HostingEnvironment.ApplicationName); + }); + }); + } + + [Fact] + public Task RunWithHostBuilderContextAsync_ShouldHaveApplicationNameEqualToThisAssembly_WithHostBuilderContext() + { + return WebHostTestFactory.RunWithHostBuilderContextAsync((context, app) => + { + Assert.NotNull(context); + Assert.NotNull(context.HostingEnvironment); + Assert.NotNull(context.Configuration); + Assert.NotNull(context.Properties); + Assert.NotNull(app); + }, + (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); + }); + }); + } + + [Fact] + public async Task RunAsync_ShouldWorkWithXunitTestLogging() + { + using var response = await WebHostTestFactory.RunAsync( + services => + { + services.AddXunitTestLogging(TestOutput); + services.AddServerTiming(o => o.SuppressHeaderPredicate = _ => false); + } + , app => + { + app.UseServerTiming(); + app.Use(async (context, next) => + { + var sw = Stopwatch.StartNew(); + context.Response.OnStarting(() => + { + sw.Stop(); + context.RequestServices.GetRequiredService().AddServerTiming("use-middleware", sw.Elapsed); + return Task.CompletedTask; + }); + await next(context).ConfigureAwait(false); + }); + app.Run(context => + { + Thread.Sleep(400); + return context.Response.WriteAsync("Hello World!"); + }); + }).ConfigureAwait(false); + + Assert.StartsWith("use-middleware;dur=", response.Headers.Single(kvp => kvp.Key == ServerTiming.HeaderName).Value.FirstOrDefault()); + } + } +}