From 3747062b081440f09e5849f4536f0aae36274cdf Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Mon, 29 Jan 2024 02:34:13 +0100 Subject: [PATCH] Add new test bases and update logging system Expanded the testing capabilities by creating HostApplicationTestBase and WebHostApplicationTestBase. These bases should make it easier to write and encapsulate common setup and teardown operations on tests involving WebHost and Host. Additionally, revised the logging system to include a "SimpleTestLogger" that operates without dependencies on the existing PulseFlow system. Made adjustments to related classes accordingly. --- .../DbContextBuilder.cs | 21 +++++- .../LoggingBuilderExtensions.cs | 20 ++++- .../ServiceCollectionExtensions.cs | 17 +++++ Frank.Testing.Logging/SimpleTestLogger.cs | 4 +- .../SimpleTestLoggerProvider.cs | 22 ++++++ .../Frank.Testing.TestBases.csproj | 21 ++++++ .../HostApplicationTestBase.cs | 43 +++++++++++ .../WebHostApplicationTestBase.cs | 46 ++++++++++++ Frank.Testing.TestBases/WebHostExtensions.cs | 25 +++++++ .../TestOutputCSharpExtensions.cs | 7 -- .../TestOutputXmlExtensions.cs | 4 +- .../DbContextBuilderTests.cs | 51 +++++++------ .../Frank.Testing.Tests.csproj | 2 + .../TestBases/HostApplicationTestBaseTests.cs | 54 ++++++++++++++ .../WebHostApplicationTestBaseTests.cs | 74 +++++++++++++++++++ .../TestLogging/TestLoggingTests.cs | 8 +- Frank.Testing.sln | 6 ++ README.md | 4 +- 18 files changed, 386 insertions(+), 43 deletions(-) create mode 100644 Frank.Testing.Logging/SimpleTestLoggerProvider.cs create mode 100644 Frank.Testing.TestBases/Frank.Testing.TestBases.csproj create mode 100644 Frank.Testing.TestBases/HostApplicationTestBase.cs create mode 100644 Frank.Testing.TestBases/WebHostApplicationTestBase.cs create mode 100644 Frank.Testing.TestBases/WebHostExtensions.cs create mode 100644 Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs create mode 100644 Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs diff --git a/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs b/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs index 8bfc90d..d40ea4c 100644 --- a/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs +++ b/Frank.Testing.EntityFrameworkCore/DbContextBuilder.cs @@ -1,5 +1,4 @@ using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -17,6 +16,8 @@ public class DbContextBuilder where T : DbContext private ILoggerFactory? _loggerFactory; private string _sqliteConnectionString = "Data Source=:memory:"; + + private string _databaseName = "TestDatabase"; public DbContextBuilder WithLoggerProvider(ILoggerProvider loggerProvider) { @@ -36,12 +37,30 @@ public DbContextBuilder WithService(Action conf return this; } + public DbContextBuilder WithLoggerFactory(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + return this; + } + public DbContextBuilder WithOptions(Action> configureOptions) { _configuredOptions = configureOptions as Action; return this; } + public DbContextBuilder WithDatabaseName(string databaseName) + { + _databaseName = databaseName; + return this; + } + + public DbContextBuilder WithRandomDatabaseName() + { + _databaseName = Guid.NewGuid().ToString(); + return this; + } + public T Build() { _serviceCollection.AddDbContext(OptionsAction); diff --git a/Frank.Testing.Logging/LoggingBuilderExtensions.cs b/Frank.Testing.Logging/LoggingBuilderExtensions.cs index 736375d..52f0c24 100644 --- a/Frank.Testing.Logging/LoggingBuilderExtensions.cs +++ b/Frank.Testing.Logging/LoggingBuilderExtensions.cs @@ -19,7 +19,6 @@ public static class LoggingBuilderExtensions /// The modified ILoggingBuilder with the test logging added. public static ILoggingBuilder AddPulseFlowTestLoggingProvider(this ILoggingBuilder builder, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) { - builder.ClearProviders(); builder.AddPulseFlow(); builder.Services.AddSingleton(outputHelper); builder.Services.Configure(options => @@ -29,4 +28,21 @@ public static ILoggingBuilder AddPulseFlowTestLoggingProvider(this ILoggingBuild builder.Services.AddPulseFlow(flowBuilder => flowBuilder.AddFlow()); return builder; } -} \ No newline at end of file + + public static ILoggingBuilder AddSimpleTestLoggingProvider(this ILoggingBuilder builder, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) + { + builder.Services.AddSingleton(outputHelper); + builder.Services.Configure(options => + { + options.MinLevel = logLevel; + }); + builder.AddProvider(); + return builder; + } + + public static ILoggingBuilder AddProvider(this ILoggingBuilder builder) where T : class, ILoggerProvider + { + builder.Services.AddSingleton(); + return builder; + } +} diff --git a/Frank.Testing.Logging/ServiceCollectionExtensions.cs b/Frank.Testing.Logging/ServiceCollectionExtensions.cs index 9ef25e3..e04386f 100644 --- a/Frank.Testing.Logging/ServiceCollectionExtensions.cs +++ b/Frank.Testing.Logging/ServiceCollectionExtensions.cs @@ -23,4 +23,21 @@ public static IServiceCollection AddTestLogging(this IServiceCollection services services.AddLogging(builder => builder.AddPulseFlowTestLoggingProvider(outputHelper, logLevel)); return services; } + + /// + /// Adds simple test logging to the IServiceCollection. + /// + /// The IServiceCollection to add the test logging to. + /// The ITestOutputHelper to redirect the logging output to. + /// The log level to use for the test logging. Default is LogLevel.Debug. + /// The modified IServiceCollection with the test logging added. + public static IServiceCollection AddSimpleTestLogging(this IServiceCollection services, ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Debug) + { + services.Configure(options => + { + options.MinLevel = logLevel; + }); + services.AddLogging(builder => builder.AddSimpleTestLoggingProvider(outputHelper, logLevel)); + return services; + } } \ No newline at end of file diff --git a/Frank.Testing.Logging/SimpleTestLogger.cs b/Frank.Testing.Logging/SimpleTestLogger.cs index 1119b31..fa185fe 100644 --- a/Frank.Testing.Logging/SimpleTestLogger.cs +++ b/Frank.Testing.Logging/SimpleTestLogger.cs @@ -11,8 +11,6 @@ public class SimpleTestLogger(ITestOutputHelper outputHelper, LogLevel logLev public class SimpleTestLogger(ITestOutputHelper outputHelper, LogLevel level, string categoryName) : ILogger { - private string _categoryName = categoryName; - public IDisposable? BeginScope(TState state) where TState : notnull => new PulseFlowLoggerScope(state); @@ -23,6 +21,6 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except if (logLevel < level) return; - outputHelper.WriteLine(new LogPulse(logLevel, eventId, exception, _categoryName, formatter.Invoke(state, exception), state as IReadOnlyList>).ToString()); + outputHelper.WriteLine(new LogPulse(logLevel, eventId, exception, categoryName, formatter.Invoke(state, exception), state as IReadOnlyList>).ToString()); } } \ No newline at end of file diff --git a/Frank.Testing.Logging/SimpleTestLoggerProvider.cs b/Frank.Testing.Logging/SimpleTestLoggerProvider.cs new file mode 100644 index 0000000..3e5b0bb --- /dev/null +++ b/Frank.Testing.Logging/SimpleTestLoggerProvider.cs @@ -0,0 +1,22 @@ +using System.Collections.Concurrent; + +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +using Xunit.Abstractions; + +namespace Frank.Testing.Logging; + +public class SimpleTestLoggerProvider(ITestOutputHelper outputHelper, IOptionsMonitor options) : ILoggerProvider +{ + private readonly ConcurrentDictionary _loggers = new(); + + /// + public void Dispose() + { + _loggers.Clear(); + } + + /// + public ILogger CreateLogger(string categoryName) => _loggers.GetOrAdd(categoryName, new SimpleTestLogger(outputHelper, options.CurrentValue.MinLevel, categoryName)); +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj b/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj new file mode 100644 index 0000000..76ed464 --- /dev/null +++ b/Frank.Testing.TestBases/Frank.Testing.TestBases.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + + + + + + + + + + + + + + + diff --git a/Frank.Testing.TestBases/HostApplicationTestBase.cs b/Frank.Testing.TestBases/HostApplicationTestBase.cs new file mode 100644 index 0000000..a9bb85f --- /dev/null +++ b/Frank.Testing.TestBases/HostApplicationTestBase.cs @@ -0,0 +1,43 @@ +using Frank.Testing.Logging; + +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit; +using Xunit.Abstractions; + +namespace Frank.Testing.TestBases; + +public abstract class HostApplicationTestBase : IAsyncLifetime +{ + private readonly HostApplicationBuilder _hostApplicationBuilder; + private IHost? _host; + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private bool _initialized = false; + + protected HostApplicationTestBase(ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Information) + { + _hostApplicationBuilder = Host.CreateEmptyApplicationBuilder(new HostApplicationBuilderSettings()); + _hostApplicationBuilder.Logging.AddSimpleTestLoggingProvider(outputHelper, logLevel); + } + + public IServiceProvider Services => (_initialized ? _host?.Services : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + + protected virtual async Task SetupAsync(HostApplicationBuilder builder) => await Task.CompletedTask; + + public async Task InitializeAsync() + { + await SetupAsync(_hostApplicationBuilder); + _host = _hostApplicationBuilder.Build(); + await _host.StartAsync(_cancellationTokenSource.Token); + _initialized = true; + } + + public async Task DisposeAsync() + { + await _cancellationTokenSource.CancelAsync(); + await _host?.StopAsync()!; + await _host.WaitForShutdownAsync(); + _host.Dispose(); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/WebHostApplicationTestBase.cs b/Frank.Testing.TestBases/WebHostApplicationTestBase.cs new file mode 100644 index 0000000..926d1d7 --- /dev/null +++ b/Frank.Testing.TestBases/WebHostApplicationTestBase.cs @@ -0,0 +1,46 @@ +using Frank.Testing.Logging; + +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit; +using Xunit.Abstractions; + +namespace Frank.Testing.TestBases; + +public abstract class WebHostApplicationTestBase : IAsyncLifetime +{ + private readonly IWebHostBuilder _hostApplicationBuilder; + private IWebHost? _host; + private readonly CancellationTokenSource _cancellationTokenSource = new(); + private bool _initialized = false; + + protected WebHostApplicationTestBase(ITestOutputHelper outputHelper, LogLevel logLevel = LogLevel.Information) + { + _hostApplicationBuilder = WebHost.CreateDefaultBuilder(); + _hostApplicationBuilder.ConfigureLogging(logging => logging.AddSimpleTestLoggingProvider(outputHelper, logLevel)); + } + + public IServiceProvider Services => (_initialized ? _host?.Services : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + + protected virtual async Task SetupAsync(IWebHostBuilder builder) => await Task.CompletedTask; + + protected HttpClient TestClient => (_initialized ? _host?.CreateTestClient() : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + protected IEnumerable GetServerEndpoints() => (_initialized ? _host?.GetServerEndpoints() : throw new InvalidOperationException("The host has not been initialized yet.")) ?? throw new InvalidOperationException("!!!"); + public async Task InitializeAsync() + { + await SetupAsync(_hostApplicationBuilder); + _host = _hostApplicationBuilder.Build(); + await _host.StartAsync(_cancellationTokenSource.Token); + _initialized = true; + } + + public async Task DisposeAsync() + { + await _cancellationTokenSource.CancelAsync(); + await _host?.StopAsync()!; + await _host.WaitForShutdownAsync(); + _host.Dispose(); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestBases/WebHostExtensions.cs b/Frank.Testing.TestBases/WebHostExtensions.cs new file mode 100644 index 0000000..80ae8f6 --- /dev/null +++ b/Frank.Testing.TestBases/WebHostExtensions.cs @@ -0,0 +1,25 @@ +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.Hosting.Server.Features; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +namespace Frank.Testing.TestBases; + +public static class WebHostExtensions +{ + public static HttpClient CreateTestClient(this IWebHost host) + { + var baseAddress = host.ServerFeatures.Get()?.Addresses.First(); + + return new HttpClient + { + BaseAddress = new Uri(baseAddress ?? throw new InvalidOperationException("The host has not been initialized yet."), UriKind.Absolute) + }; + } + + public static IEnumerable GetServerEndpoints(this IWebHost host) + { + return host.Services.GetServices().SelectMany(x => x.Endpoints).Select(x => x.DisplayName); + } +} \ No newline at end of file diff --git a/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs index 5e83731..bb29e2c 100644 --- a/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs +++ b/Frank.Testing.TestOutputExtensions/TestOutputCSharpExtensions.cs @@ -63,11 +63,4 @@ public static void WriteCSharp(this ITestOutputHelper outputHelper, IEnumerab SortDirection = ListSortDirection.Ascending, MaxDepth = 64, }; -} - -public enum CSharpDumpType -{ - Variable, - Class, - IEnumerable } \ No newline at end of file diff --git a/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs index 19c05b5..38c290f 100644 --- a/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs +++ b/Frank.Testing.TestOutputExtensions/TestOutputXmlExtensions.cs @@ -13,7 +13,7 @@ public static void WriteXml(this ITestOutputHelper outputHelper, T source, Xm using var textWriter = new StringWriter(); using var xmlWriter = XmlWriter.Create(textWriter, settings); var xmlSerializer = new XmlSerializerFactory().CreateSerializer(typeof(T)); - xmlSerializer.Serialize(xmlWriter, source); + xmlSerializer.Serialize(xmlWriter, source, new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty })); outputHelper.WriteLine(textWriter.ToString()); } @@ -24,6 +24,6 @@ public static void WriteXml(this ITestOutputHelper outputHelper, T source, Xm NewLineChars = "\n", NewLineHandling = NewLineHandling.Replace, OmitXmlDeclaration = false, - Encoding = new UTF8Encoding(false), + Encoding = new UTF8Encoding(false) }; } \ No newline at end of file diff --git a/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs b/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs index 5904d46..73bc729 100644 --- a/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs +++ b/Frank.Testing.Tests/EntityFramworkCoreTests/DbContextBuilderTests.cs @@ -1,6 +1,4 @@ -using Frank.PulseFlow; -using Frank.PulseFlow.Logging; -using Frank.Testing.EntityFrameworkCore; +using Frank.Testing.EntityFrameworkCore; using Frank.Testing.Logging; using Frank.Testing.Tests.TestingInfrastructure; @@ -10,6 +8,8 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using NSubstitute; + using Xunit.Abstractions; namespace Frank.Testing.Tests.EntityFramworkCoreTests; @@ -19,7 +19,10 @@ public class DbContextBuilderTests(ITestOutputHelper outputHelper) [Fact] public void Build_WithLoggerProvider_UsesLoggerProvider() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .Build(); dbContext.Database.EnsureCreated(); dbContext.Database.ExecuteSqlRaw("SELECT 1"); @@ -29,7 +32,10 @@ public void Build_WithLoggerProvider_UsesLoggerProvider() [Fact] public void Build_WithService_UsesService() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithService(services => services.AddSingleton()) .Build(); Assert.NotNull(dbContext.GetService()); @@ -38,7 +44,10 @@ public void Build_WithService_UsesService() [Fact] public void Build_WithOptions_UsesOptions() { + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithOptions(options => options.UseSqlite("Data Source=:memory:")) .Build(); dbContext.Database.EnsureCreated(); @@ -49,8 +58,10 @@ public void Build_WithOptions_UsesOptions() [Fact] public void Build_WithLoggerProviderAndService_UsesLoggerProviderAndService() { - var conduit = new TestConduit(); + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithSqliteConnectionString("Data Source=MyTestDatabase.db") .WithService(services => services.AddSingleton()) .Build(); @@ -60,24 +71,13 @@ public void Build_WithLoggerProviderAndService_UsesLoggerProviderAndService() dbContext.Dispose(); } - public class TestService : ITestService - { - public async Task DoSomethingAsync() - { - await Task.CompletedTask; - } - } - - public interface ITestService - { - Task DoSomethingAsync(); - } - [Fact] public void Build_WithLoggerProviderAndOptions_UsesLoggerProviderAndOptions() { - var conduit = new TestConduit(); + var options = Substitute.For>(); + options.CurrentValue.Returns(new LoggerFilterOptions() { MinLevel = LogLevel.Debug }); var dbContext = new DbContextBuilder() + .WithLoggerProvider(new SimpleTestLoggerProvider(outputHelper, options)) .WithSqliteConnectionString("Data Source=MyTestDatabase.db") .Build(); dbContext.Database.EnsureCreated(); @@ -86,17 +86,20 @@ public void Build_WithLoggerProviderAndOptions_UsesLoggerProviderAndOptions() dbContext.Database.ExecuteSqlRaw("SELECT 1"); dbContext.Dispose(); - outputHelper.WriteJson(conduit.Logs); } - public class TestConduit : IConduit + + + public class TestService : ITestService { - public async Task SendAsync(IPulse message) + public async Task DoSomethingAsync() { await Task.CompletedTask; - Logs.Add(message as LogPulse ?? throw new InvalidOperationException()); } - - public List Logs { get; } = new(); + } + + public interface ITestService + { + Task DoSomethingAsync(); } } diff --git a/Frank.Testing.Tests/Frank.Testing.Tests.csproj b/Frank.Testing.Tests/Frank.Testing.Tests.csproj index 0d61dde..9e82f46 100644 --- a/Frank.Testing.Tests/Frank.Testing.Tests.csproj +++ b/Frank.Testing.Tests/Frank.Testing.Tests.csproj @@ -30,6 +30,8 @@ + + diff --git a/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs b/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs new file mode 100644 index 0000000..08431a3 --- /dev/null +++ b/Frank.Testing.Tests/TestBases/HostApplicationTestBaseTests.cs @@ -0,0 +1,54 @@ +using FluentAssertions; + +using Frank.Testing.TestBases; + +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests.TestBases; + +public class HostApplicationTestBaseTests(ITestOutputHelper outputHelper) : HostApplicationTestBase(outputHelper) +{ + protected override Task SetupAsync(HostApplicationBuilder builder) + { + builder.Services.AddHostedService(); + builder.Services.AddSingleton(); + return Task.CompletedTask; + } + + [Fact] + public async Task Test() + { + await Task.Delay(2500); + } + + [Fact] + public void Test2() + { + var service = Services.GetService(); + service.Should().NotBeNull(); + } + + public class TestService2 + { + public TestService2(ILogger logger) + { + logger.LogInformation("Foo"); + } + } + + public class TestService(ILogger logger) : BackgroundService + { + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + await Task.Delay(1000, stoppingToken); + logger.LogInformation("Hello, world!"); + } + } + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs b/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs new file mode 100644 index 0000000..07aa9a1 --- /dev/null +++ b/Frank.Testing.Tests/TestBases/WebHostApplicationTestBaseTests.cs @@ -0,0 +1,74 @@ +using System.Net; + +using FluentAssertions; + +using Frank.Testing.TestBases; + +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; + +using Xunit.Abstractions; + +namespace Frank.Testing.Tests.TestBases; + +public class WebHostApplicationTestBaseTests(ITestOutputHelper outputHelper) : WebHostApplicationTestBase(outputHelper) +{ + protected override Task SetupAsync(IWebHostBuilder builder) + { + builder.ConfigureServices((context, services) => + { + services.AddControllersWithViews(); + }); + builder.Configure((context, app) => + { + app.UseRouting(); + app.UseEndpoints(endpoints => + { + // endpoints.MapHealthChecks("/health"); + endpoints.MapControllers(); + endpoints.MapGet("/test1", async httpContext => + { + await httpContext.Response.WriteAsync("Test1 endpoint"); + }); + + }); + }); + return Task.CompletedTask; + } + + [Fact] + public async Task Test() + { + var response = await TestClient.GetAsync("/test1"); + var content = await response.Content.ReadAsStringAsync(); + content.Should().Be("Test1 endpoint"); + } + + [Fact] + public async Task Test2() + { + var response = await TestClient.GetAsync("/test2"); + var content = await response.Content.ReadAsStringAsync(); + content.Should().Be("Test2 endpoint"); + } + + [Fact] + public void Test3() + { + var endpoints = GetServerEndpoints(); + // endpoints = Enumerable.Empty(); + outputHelper.WriteLine(string.Join(Environment.NewLine, endpoints)); + } +} + +public class MyController : ControllerBase +{ + [HttpGet("/test2")] + public IActionResult Test2() + { + return Ok("Test2 endpoint"); + } +} \ No newline at end of file diff --git a/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs b/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs index 63a668b..ae94b03 100644 --- a/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs +++ b/Frank.Testing.Tests/TestLogging/TestLoggingTests.cs @@ -24,7 +24,10 @@ private IHostBuilder CreateHostBuilder() return Host.CreateDefaultBuilder() .ConfigureLogging(logging => { - logging.AddPulseFlowTestLoggingProvider(outputHelper, LogLevel.Information); + logging + .AddPulseFlowTestLoggingProvider(outputHelper, LogLevel.Information) + // .AddSimpleTestLoggingProvider(outputHelper, LogLevel.Information) + ; }) .ConfigureServices((context, services) => { @@ -37,9 +40,10 @@ private class MyService(ILogger logger) : BackgroundService protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using var scope = logger.BeginScope("Titans are {Description}", "awesome"); + var counter = 0; while (!stoppingToken.IsCancellationRequested) { - logger.LogInformation("Hello from MyService"); + logger.LogInformation("Hello from MyService {Counter}", counter++); await Task.Delay(100, stoppingToken); } } diff --git a/Frank.Testing.sln b/Frank.Testing.sln index 58df3c9..e7e2343 100644 --- a/Frank.Testing.sln +++ b/Frank.Testing.sln @@ -26,6 +26,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.EntityFramewo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.Testcontainers", "Frank.Testing.Testcontainers\Frank.Testing.Testcontainers.csproj", "{13E7B32B-CBA5-4BA3-854B-697B835796F7}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Frank.Testing.TestBases", "Frank.Testing.TestBases\Frank.Testing.TestBases.csproj", "{33258CFE-D91E-42A4-80CB-A47CB954A53A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -59,5 +61,9 @@ Global {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Debug|Any CPU.Build.0 = Debug|Any CPU {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Release|Any CPU.ActiveCfg = Release|Any CPU {13E7B32B-CBA5-4BA3-854B-697B835796F7}.Release|Any CPU.Build.0 = Release|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {33258CFE-D91E-42A4-80CB-A47CB954A53A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/README.md b/README.md index d7eeef0..8602eff 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ A set of nugets to allow for easier testing of dotnet code using xUnit ___ [![GitHub License](https://img.shields.io/github/license/frankhaugen/Frank.Testing)](LICENSE) -[![NuGet](https://img.shields.io/nuget/v/Frank.Testing.svg)](https://www.nuget.org/packages/Frank.Testing) -[![NuGet](https://img.shields.io/nuget/dt/Frank.Testing.svg)](https://www.nuget.org/packages/Frank.Testing) +[![NuGet](https://img.shields.io/nuget/v/Frank.Testing.Logging.svg)](https://www.nuget.org/packages/Frank.Testing.Logging) +[![NuGet](https://img.shields.io/nuget/dt/Frank.Testing.Logging.svg)](https://www.nuget.org/packages/Frank.Testing.Logging) ![GitHub contributors](https://img.shields.io/github/contributors/frankhaugen/Frank.Testing) ![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/frankhaugen/Frank.Testing)