### ASP.NET Core Unit Test Example with WebHostTest Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Demonstrates how to create a custom web fixture and test class using WebHostTest. Includes service configuration, application pipeline setup, and an example test case. ```csharp public class MyWebFixture : ManagedWebHostFixture { // Fixture can configure services and host } public class MyWebTest : WebHostTest { private readonly HttpClient _client; public MyWebTest(MyWebFixture fixture, ITestOutputHelper output) : base(fixture, output) { _client = new HttpClient { BaseAddress = new Uri("http://localhost") }; } public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); } public override void ConfigureApplication(IApplicationBuilder app) { // Configure middleware app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/api/weather", WeatherHandler); }); } [Fact] public async Task GetWeatherReturnsOk() { var response = await _client.GetAsync("/api/weather"); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } private static IResult WeatherHandler() { return Results.Ok(new { temperature = 72, condition = "Sunny" }); } } ``` -------------------------------- ### Configure ASP.NET Core Pipeline (C#) Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/README.md Set up the ASP.NET Core application pipeline within your tests. This example configures basic routing and a simple GET endpoint. ```csharp public override void ConfigureApplication(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => endpoints.MapGet("/", () => "OK")); } ``` -------------------------------- ### Complete Fixture Configuration Example Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Example of a complete xUnit test fixture configuration using ManagedHostFixture. This includes setting up connection strings, registering scoped repositories, configuring logging, and adding an HTTP client for integration testing. ```csharp public class TestDatabaseFixture : ManagedHostFixture { private string _connectionString; public TestDatabaseFixture() { ConfigureCallback = (config, env) => { // Load test database connection string _connectionString = config.GetConnectionString("TestDb"); if (string.IsNullOrEmpty(_connectionString)) { throw new InvalidOperationException("TestDb connection string not configured"); } }; ConfigureServicesCallback = services => { // Register database context services.AddDbContext(options => options.UseSqlServer(_connectionString) ); // Register repositories services.AddScoped(); services.AddScoped(); // Configure logging services.AddXunitTestLogging(LogLevel.Debug); // Add HTTP client for integration testing services.AddHttpClient(); }; ConfigureHostCallback = hb => { hb.ConfigureLogging(logging => { logging.SetMinimumLevel(LogLevel.Trace); logging.AddConsole(); }); }; } } // appsettings.json { "ConnectionStrings": { "TestDb": "Server=(LocalDB)\mssqllocaldb;Database=XunitTests;Integrated Security=true;" }, "Logging": { "LogLevel": { "Default": "Information" } } } ``` -------------------------------- ### WildcardOptions Usage Examples Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/types.md Demonstrates creating WildcardOptions with default and custom settings, and using them with the Test.Match method for pattern matching. ```csharp // Default wildcard options var options1 = new WildcardOptions(); Assert.Equal("\\*", options1.GroupOfCharacters); Assert.Equal("\\?", options1.SingleCharacter); ``` ```csharp // Custom wildcard characters var options2 = new WildcardOptions { GroupOfCharacters = "%", SingleCharacter = "_", ThrowOnNoMatch = true }; ``` ```csharp // Use with Test.Match Test.Match( "Expected%Pattern", "ExpectedAnyPattern", opt => { opt.GroupOfCharacters = "%"; opt.ThrowOnNoMatch = true; } ); ``` -------------------------------- ### HttpClient Example for WebHostTest Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/types.md Demonstrates how to create and use an HttpClient within a WebHostTest to make requests to a test server. Ensure the fixture provides a valid server instance. ```csharp public class MyWebTest : WebHostTest { private readonly HttpClient _client; public MyWebTest(MyWebFixture fixture, ITestOutputHelper output) : base(fixture, output) { _client = fixture.Server?.CreateClient(); } [Fact] public async Task ApiReturnsOk() { var response = await _client.GetAsync("/api/data"); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } } ``` -------------------------------- ### Initialize InMemoryTestStore Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Initializes a new empty in-memory store. No specific setup is required. ```csharp public InMemoryTestStore() ``` -------------------------------- ### Test Store Usage Example Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Demonstrates adding items to an InMemoryTestStore, checking the count, querying by predicate, querying by type, and using LINQ for advanced filtering. ```csharp [Fact] public void TestStoreQuery() { var store = new InMemoryTestStore(); store.Add("Hello"); store.Add(42); store.Add("World"); store.Add(3.14); // Count all items Assert.Equal(4, store.Count); // Query with predicate var strings = store.Query(x => x is string).Cast(); Assert.Equal(2, strings.Count()); // Query by type var numbers = store.QueryFor(); Assert.Single(numbers); Assert.Equal(42, numbers.First()); // Query with LINQ var filtered = store.Query().Where(x => x is string).Cast().Where(s => s.Length > 4); Assert.Single(filtered); Assert.Equal("Hello", filtered.First()); } ``` -------------------------------- ### Example Usage of AddXunitTestLogging in MyHostFixture Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/extensions-and-utilities.md Demonstrates how to configure xUnit logging within a test fixture's service collection. ```csharp public class MyHostFixture : ManagedHostFixture { public MyHostFixture() { ConfigureServicesCallback = services => { // Add xUnit logging with minimum log level services.AddXunitTestLogging(LogLevel.Information); // Or with specific output helper services.AddXunitTestLogging(testOutput, LogLevel.Debug); // Add other services services.AddScoped(); }; } } ``` -------------------------------- ### Complete HostTest Example with Service Registration and Host Configuration Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Demonstrates a complete xUnit test class using HostTest. It shows how to implement ConfigureServices to register scoped services and ConfigureHost to add in-memory configuration. Includes a sample test method to verify service registration. ```csharp public class MyHostFixture : ManagedHostFixture { } public class MyHostTest : HostTest { public MyHostTest(MyHostFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); services.AddScoped(); } protected override void ConfigureHost(IHostBuilder hb) { // Optional: further customize the host builder hb.ConfigureAppConfiguration((ctx, cfg) => { cfg.AddInMemoryCollection(new Dictionary { ["TestKey"] = "TestValue" }); }); } [Fact] public async Task ServiceIsRegistered() { var emailService = Host.Services.GetRequiredService(); Assert.NotNull(emailService); var result = await emailService.SendAsync("test@example.com", "Test"); Assert.True(result); } ``` -------------------------------- ### Custom Log Store Example Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Demonstrates creating a custom store derived from InMemoryTestStore for specific logging scenarios. Includes methods for retrieving error messages and asserting no errors. ```csharp public class LogStore : InMemoryTestStore { public LogStore() { } public IEnumerable GetErrorMessages() { return QueryFor() .Select(e => e.Message); } public void AssertNoErrors() { var errors = QueryFor(); Assert.Empty(errors); } } public abstract class LogEntry { public string Message { get; set; } } public class ErrorLogEntry : LogEntry { } public class InfoLogEntry : LogEntry { } [Fact] public void TestLogging() { var store = new LogStore(); store.Add(new InfoLogEntry { Message = "App started" }); store.Add(new ErrorLogEntry { Message = "Connection failed" }); store.Add(new InfoLogEntry { Message = "Retrying..." }); Assert.Equal(3, store.Count); Assert.Single(store.QueryFor()); Assert.Equal(2, store.QueryFor().Count()); } ``` -------------------------------- ### Configure Application Pipeline via Callback Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Use this callback to configure the application pipeline when using IWebHostFixture. It allows for dynamic pipeline setup. ```csharp public class MyWebFixture : ManagedWebHostFixture { public MyWebFixture() { ConfigureApplicationCallback = app => { app.UseRouting(); app.UseEndpoints(endpoints => endpoints.MapGet("/", () => "OK")); }; } } ``` -------------------------------- ### appsettings.Environment.json Configuration Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Environment-specific settings that override appsettings.json. Example shown for the Development environment. ```json { "ApiUrl": "https://localhost:5000", "TimeoutSeconds": 10, "Debug": true } ``` -------------------------------- ### Test Captured Logs with InMemoryTestStore Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/types.md Demonstrates how to use InMemoryTestStore to capture and query XunitTestLoggerEntry instances. This example simulates logging and asserts specific error messages and severity. ```csharp [Fact] public void TestCapturedLogs() { var store = new InMemoryTestStore(); // Simulate logging store.Add(new XunitTestLoggerEntry(LogLevel.Information, new EventId(1), "App started")); store.Add(new XunitTestLoggerEntry(LogLevel.Error, new EventId(2), "Connection failed")); var errors = store.QueryFor() .Where(e => e.Severity == LogLevel.Error); Assert.Single(errors); Assert.Equal("Connection failed", errors.First().Message); Assert.Equal("Connection failed", errors.First().ToString()); } ``` -------------------------------- ### Environment Variables Configuration Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Configuration values can be provided via environment variables using the standard ':' separator for hierarchical keys. Examples shown for setting variables. ```bash # Set from environment LOGGING__LOGLEVEL__DEFAULT=Debug APIURL=https://test.example.com ``` -------------------------------- ### HostFixture InitializeAsync Method Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-fixtures.md The primary method for asynchronous initialization, called by xUnit before tests execute. Override this to perform setup tasks that require asynchronous operations. ```csharp public virtual ValueTask InitializeAsync() ``` -------------------------------- ### ManagedHostFixture ConfigureServicesCallback Example Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-fixtures.md Demonstrates how to use the ConfigureServicesCallback to register custom services within a ManagedHostFixture. This is useful for providing dependencies to your tests. ```csharp public class MyFixture : ManagedHostFixture { public MyFixture() { ConfigureServicesCallback = services => { services.AddScoped(); }; ConfigureCallback = (config, env) => { // Access Configuration and Environment }; } } public class MyTest : HostTest { public MyTest(MyFixture fixture, ITestOutputHelper output) : base(fixture, output) { } [Fact] public void MyTest() { var service = Host.Services.GetRequiredService(); Assert.NotNull(service); } public override void ConfigureServices(IServiceCollection services) { // Additional services specific to this test } } ``` -------------------------------- ### EventId Usage Example Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/types.md Demonstrates how to create an EventId and use it with XunitTestLoggerEntry. Asserts the Id and Name properties of the created entry. ```csharp var eventId = new EventId(100, "UserLogin"); var entry = new XunitTestLoggerEntry(LogLevel.Information, eventId, "User logged in"); Assert.Equal(100, entry.Id.Id); Assert.Equal("UserLogin", entry.Id.Name); ``` -------------------------------- ### Async Initialization and Cleanup for External Services Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md Use this pattern to perform asynchronous setup and teardown operations, such as waiting for an external service to become ready or cleaning up external resources. Inherit from ManagedHostFixture and override InitializeAsync and OnDisposeManagedResourcesAsync. ```csharp public class ExternalServiceFixture : ManagedHostFixture { public override async ValueTask InitializeAsync() { // Wait for external service to be ready await WaitForServiceReadiness(); await base.InitializeAsync(); } protected override async ValueTask OnDisposeManagedResourcesAsync() { // Cleanup external resources await CleanupExternalService(); await base.OnDisposeManagedResourcesAsync(); } private async Task WaitForServiceReadiness() { /* ... */ } private async Task CleanupExternalService() { /* ... */ } } public class ExternalServiceTests : HostTest { public ExternalServiceTests(ExternalServiceFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { services.AddHttpClient(); } [Fact] public async Task CanCallExternalService() { var client = Host.Services.GetRequiredService(); var result = await client.GetDataAsync(); Assert.NotNull(result); } } ``` -------------------------------- ### Default Async Host Runner Callback Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md The default AsyncHostRunnerCallback handles starting the host, including synchronization context to prevent deadlocks. Avoid changing this unless you have specific async startup requirements. ```csharp protected Func AsyncHostRunnerCallback { get; set; } ``` ```csharp async (host, cancellationToken) => { if (SynchronizationContext.Current == null) { await host.StartAsync(cancellationToken); } else { Task.Run(async () => { await host.StartAsync(cancellationToken); }).GetAwaiter().GetResult(); } } ``` -------------------------------- ### HostTest Constructor with Skip Initialization Option Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Initializes the test, allowing for an option to skip host fixture initialization. This constructor is useful when manual control over fixture setup is needed. It inherits from HostTest and accepts similar parameters. ```csharp protected HostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(output, callerType) ``` -------------------------------- ### Test Line Endings Normalization Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/extensions-and-utilities.md This example demonstrates how to use the ReplaceLineEndings method to normalize different newline characters to the platform standard and also with a custom replacement string. ```csharp [Fact] public void TestLineEndings() { // Convert various line endings to platform standard var windowsText = "Line1\r\nLine2\r\nLine3"; var unixText = "Line1\nLine2\nLine3"; var macText = "Line1\rLine2\rLine3"; var normalized1 = windowsText.ReplaceLineEndings(); var normalized2 = unixText.ReplaceLineEndings(); var normalized3 = macText.ReplaceLineEndings(); // All are now equal with platform line endings Assert.Equal(normalized1, normalized2); Assert.Equal(normalized2, normalized3); // Custom replacement var htmlFormatted = "Line1\r\nLine2\r\nLine3".ReplaceLineEndings("
"); Assert.Equal("Line1
Line2
Line3", htmlFormatted); } ``` -------------------------------- ### Define a test class inheriting from Test base class Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Example of how to define a test class that inherits from the `Test` base class provided by `Codebelt.Extensions.Xunit`. The constructor must accept and pass `ITestOutputHelper` to the base class. ```csharp using Codebelt.Extensions.Xunit; using Xunit; namespace Codebelt.Extensions.Xunit // Same as SUT { public class YourTestClass : Test { public YourTestClass(ITestOutputHelper output) : base(output) { } } } ``` -------------------------------- ### Get All Captured Logs Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/logging-utilities.md Retrieve all log entries captured during the test execution. This is the starting point for querying logs. ```csharp var allLogs = Host.Services .GetRequiredService>() .Query(); ``` -------------------------------- ### Build entire solution Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Use this command to build the entire solution. It compiles all projects within the solution file. ```bash dotnet build Codebelt.Extensions.Xunit.slnx ``` -------------------------------- ### Hosting Support Using Statement Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Import the namespace for hosting and dependency injection support from Codebelt.Extensions.Xunit. ```csharp // Hosting/DI support using Codebelt.Extensions.Xunit.Hosting; ``` -------------------------------- ### Get Store Count Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Retrieves the number of elements currently stored. This property is read-only. ```csharp public int Count { get; } ``` -------------------------------- ### ManagedWebHostFixture Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-index.md Default fixture for managing the lifecycle of a web host during tests. Simplifies setup and teardown of the host. ```APIDOC ## Class ManagedWebHostFixture ### Description Default web host fixture. ### Purpose Default fixture for managing the lifecycle of a web host during tests. ``` -------------------------------- ### WebApplicationTestFactory Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-index.md Factory class for creating instances of `WebApplicationTest`. Facilitates the setup of tests for ASP.NET Core web applications. ```APIDOC ## Class WebApplicationTestFactory ### Description Factory for WebApplicationTest. ### Purpose Factory class for creating instances of `WebApplicationTest`. ``` -------------------------------- ### ManagedHostFixture ConfigureHostCallback Property Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-fixtures.md Provides a delegate to customize the IHostBuilder after its default configuration. Use this for advanced host setup. ```csharp public Action ConfigureHostCallback { get; set; } ``` -------------------------------- ### Import Meta-Package Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md This XML snippet shows how to include all Codebelt.Extensions.Xunit packages by referencing the meta-package. ```xml ``` -------------------------------- ### Build Release configuration Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Build the solution with the 'Release' configuration. This is typically used for production builds. ```bash dotnet build Codebelt.Extensions.Xunit.slnx -c Release ``` -------------------------------- ### Manually Create and Use XunitTestLogger Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/logging-utilities.md Demonstrates manual creation of an XunitTestLoggerProvider and logger instances. Allows for direct querying of captured logs based on severity. ```csharp [Fact] public void ManualLoggerCreation() { var provider = new XunitTestLoggerProvider(testOutput); var logger = provider.CreateLogger("MyTest"); logger.LogWarning("A warning"); logger.LogError("An error"); // Query captured logs var store = provider["MyTest"]; var warnings = store.Query(e => e.Severity == LogLevel.Warning); Assert.Single(warnings); } ``` -------------------------------- ### TestOutput Property Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/extensions-and-utilities.md Gets or sets the ITestOutputHelper for the current async context. Uses AsyncLocal to provide context-aware access in async code. ```APIDOC ## TestOutput ### Description Gets or sets the ITestOutputHelper for the current async context. Uses AsyncLocal to provide context-aware access in async code. Different async contexts can have different test output helpers. ### Properties - **TestOutput** (ITestOutputHelper) - Gets or sets the test output helper. ``` -------------------------------- ### HostTest Host Property Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Represents the initialized generic host instance within the HostTest base class, accessible for test setup and execution. ```csharp public IHost Host { get; protected set; } ``` -------------------------------- ### Building and Testing with SkipSignAssembly Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Use the -p:SkipSignAssembly=true flag when building or testing if the repository lacks a root .snk file for strong-name signing. ```bash dotnet build -p:SkipSignAssembly=true dotnet test -p:SkipSignAssembly=true ``` -------------------------------- ### Running DocFX Verification Commands Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Execute these commands to verify documentation builds and samples. Ensure the correct path to docfx.cs and the repository root are provided. ```bash dotnet build dotnet test dotnet run --file /scripts/docfx.cs -- --repo-root . --build-api-model --validate-samples --verify-docfx-build ``` -------------------------------- ### Write Vanilla xUnit Tests Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Demonstrates basic xUnit test structure with string matching and output logging capabilities provided by Codebelt extensions. ```csharp using Codebelt.Extensions.Xunit; using Xunit; public class StringMatchingTests : Test { public StringMatchingTests(ITestOutputHelper output) : base(output) { } [Fact] public void WildcardMatch() { Assert.True(Test.Match("Hello*World", "Hello Beautiful World")); } [Fact] public void TestOutput() { TestOutput?.WriteLine("This message appears in xUnit output"); } } ``` -------------------------------- ### Configure Host and Environment for ManagedHostFixture Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Use ConfigureCallback to load additional configuration sources or perform checks after configuration and environment are loaded, but before services are configured. The environment defaults to "Development". ```csharp public Action ConfigureCallback { get; set; } ``` ```csharp public class MyFixture : ManagedHostFixture { public MyFixture() { ConfigureCallback = (config, env) => { var apiUrl = config["ApiUrl"]; if (string.IsNullOrEmpty(apiUrl)) { throw new InvalidOperationException("ApiUrl is required"); } }; } } ``` -------------------------------- ### WebHostTest Generic Class Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Base class for ASP.NET Core unit tests using the generic host builder pattern, facilitating test setup and execution. ```APIDOC ## WebHostTest Generic Class **Namespace:** `Codebelt.Extensions.Xunit.Hosting.AspNetCore` **Location:** `src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/WebHostTest.cs` ### Summary Base class for ASP.NET Core unit tests using the generic host builder pattern. **Type Parameter:** `T` — Type implementing `IWebHostFixture` ### Constructors #### WebHostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) ```csharp protected WebHostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : this(false, hostFixture, output, callerType) ``` Initializes the test with a web host fixture. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | hostFixture | `T` | — | Implementation of IWebHostFixture | | output | `ITestOutputHelper?` | null | xUnit test output helper | | callerType | `Type?` | null | Type of the test class | #### WebHostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) ```csharp protected WebHostTest(bool skipHostFixtureInitialization, T hostFixture, ITestOutputHelper output = null, Type callerType = null) : base(skipHostFixtureInitialization, hostFixture, output, callerType) ``` Initializes with optional fixture initialization bypass. | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | skipHostFixtureInitialization | `bool` | — | If true, skips fixture initialization | | hostFixture | `T` | — | Implementation of IWebHostFixture | | output | `ITestOutputHelper?` | null | xUnit test output helper | | callerType | `Type?` | null | Type of the test class | ### Properties #### Application ```csharp public IApplicationBuilder Application { get; protected set; } ``` The configured ASP.NET Core application pipeline. ### Methods #### ConfigureApplication(IApplicationBuilder app) ```csharp public abstract void ConfigureApplication(IApplicationBuilder app) ``` Abstract method that derived classes implement to configure the HTTP request pipeline. | Parameter | Type | Description | |-----------|------|-------------| | app | `IApplicationBuilder` | The application builder to configure | **Example:** ```csharp public class MyWebFixture : ManagedWebHostFixture { // Fixture can configure services and host } public class MyWebTest : WebHostTest { private readonly HttpClient _client; public MyWebTest(MyWebFixture fixture, ITestOutputHelper output) : base(fixture, output) { _client = new HttpClient { BaseAddress = new Uri("http://localhost") }; } public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); } public override void ConfigureApplication(IApplicationBuilder app) { // Configure middleware app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/api/weather", WeatherHandler); }); } [Fact] public async Task GetWeatherReturnsOk() { var response = await _client.GetAsync("/api/weather"); Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); } private static IResult WeatherHandler() { return Results.Ok(new { temperature = 72, condition = "Sunny" }); } } ``` ``` -------------------------------- ### ManagedWebApplicationFixture Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Implementation of `IWebApplicationFixture` that bootstraps an existing ASP.NET Core application. ```APIDOC ## ManagedWebApplicationFixture Class **Namespace:** `Codebelt.Extensions.Xunit.Hosting.AspNetCore` Implementation of `IWebApplicationFixture`. Bootstraps an existing ASP.NET Core application. ``` -------------------------------- ### WebHostTest ConfigureApplication Method Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Abstract method that derived classes must implement to configure the HTTP request pipeline, including middleware and endpoints. ```csharp public abstract void ConfigureApplication(IApplicationBuilder app) ``` -------------------------------- ### Core Functionality Using Statement Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Import the core functionality namespace for Codebelt.Extensions.Xunit. ```csharp // Core functionality using Codebelt.Extensions.Xunit; ``` -------------------------------- ### HostTest Configure Method Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Allows for initialization of Configuration and Environment properties within the HostTest base class using the provided IConfiguration and IHostEnvironment. ```csharp public virtual void Configure(IConfiguration configuration, IHostEnvironment environment) ``` -------------------------------- ### Test Logging with XunitTestLoggerProvider Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/logging-utilities.md Demonstrates how to set up and use XunitTestLoggerProvider to capture and assert log messages within an xUnit test. ```csharp [Fact] public void TestLogging() { var loggerFactory = LoggerFactory.Create(builder => { var provider = new XunitTestLoggerProvider(testOutput); builder.AddProvider(provider); }); var logger = loggerFactory.CreateLogger("MyCategory"); logger.LogInformation("Test message"); // Access logs later var store = provider["MyCategory"]; var logs = store.Query(); var entry = logs.First(); Assert.Equal(LogLevel.Information, entry.Severity); Assert.Equal("Test message", entry.Message); } ``` -------------------------------- ### IAsyncLifetime Interface Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/types.md The IAsyncLifetime interface allows for asynchronous initialization and disposal of resources. xUnit calls these methods to manage the lifecycle of fixtures or test classes that require asynchronous setup or teardown. ```APIDOC ## IAsyncLifetime Interface **Namespace:** `Xunit` Defines methods for asynchronous initialization and disposal. ### Methods - `InitializeAsync()`: Called by the xUnit framework before a test method executes. - `DisposeAsync()`: Called by the xUnit framework after a test method completes. ### Implementation This interface is implemented by classes such as `Test` and `HostFixture`. ``` -------------------------------- ### ManagedHostFixture ConfigureHost Method Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-fixtures.md Creates and configures the IHost instance for testing. This method is virtual and can be overridden. ```csharp public virtual void ConfigureHost(Test hostTest) ``` -------------------------------- ### Test Middleware Pipeline Execution Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md Verify that custom and standard middleware components execute as expected within an ASP.NET Core application pipeline. This setup is useful for testing request/response modifications or the flow of control. ```csharp public class MiddlewareTests : WebHostTest { private readonly HttpClient _client; public MiddlewareTests(MyWebFixture fixture, ITestOutputHelper output) : base(fixture, output) { _client = new HttpClient { BaseAddress = new Uri("http://localhost") }; } public override void ConfigureServices(IServiceCollection services) { services.AddXunitTestLogging(); } public override void ConfigureApplication(IApplicationBuilder app) { // Custom middleware app.Use(async (context, next) => { context.Response.Headers.Add("X-Custom-Header", "TestValue"); await next(); }); // Standard middleware app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/", () => "OK"); }); } [Fact] public async Task CustomHeaderIsAdded() { var response = await _client.GetAsync("/"); Assert.True(response.Headers.Contains("X-Custom-Header")); Assert.Equal("TestValue", response.Headers.GetValues("X-Custom-Header").First()); } } ``` -------------------------------- ### Test Configuration Loading with xUnit Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md Verify that application configuration files like appsettings.json and environment variables are loaded correctly. This pattern is useful for ensuring your application's settings are accessible and valid. ```csharp public class ConfigurationTests : HostTest { public ConfigurationTests(MyFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { // Services not needed for this test } [Fact] public void AppsettingsJsonIsLoaded() { var apiUrl = Configuration["ApiUrl"]; Assert.NotNull(apiUrl); Assert.NotEmpty(apiUrl); } [Fact] public void EnvironmentVariablesAreLoaded() { // Set via appsettings.json or environment var timeout = Configuration["Timeout"]; if (!string.IsNullOrEmpty(timeout)) { Assert.True(int.TryParse(timeout, out _)); } } [Fact] public void DevelopmentEnvironmentIsUsed() { Assert.Equal("Development", Environment.EnvironmentName); } } ``` -------------------------------- ### appsettings.json Configuration Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Standard application settings loaded for all environments. This JSON file should be placed in the current directory. ```json { "Logging": { "LogLevel": { "Default": "Information" } }, "ApiUrl": "https://api.example.com", "TimeoutSeconds": 30 } ``` -------------------------------- ### Initialize XunitTestLoggerProvider Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/logging-utilities.md Initializes the logger provider. Use the constructor with ITestOutputHelperAccessor for async context support. ```csharp internal XunitTestLoggerProvider() ``` ```csharp internal XunitTestLoggerProvider(ITestOutputHelper output) ``` ```csharp internal XunitTestLoggerProvider(ITestOutputHelperAccessor accessor) ``` -------------------------------- ### Shared Fixture Across Test Collection Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md This pattern is used when multiple test classes need to share expensive setup, such as seeding a database. Define a collection definition and mark test classes with the same collection attribute to share the fixture. ```csharp public class DatabaseFixture : ManagedHostFixture, IAsyncLifetime { public override async ValueTask InitializeAsync() { await base.InitializeAsync(); // Seed database once for all tests in collection } } [CollectionDefinition("Database collection")] public class DatabaseCollection : ICollectionFixture { // Mark all tests with [Collection("Database collection")] to share fixture } [Collection("Database collection")] public class UserRepositoryTests : HostTest { public UserRepositoryTests(DatabaseFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { } [Fact] public void UsersAreSeeded() { var repo = Host.Services.GetRequiredService(); Assert.NotEmpty(repo.GetAll()); } } [Collection("Database collection")] public class ProductRepositoryTests : HostTest { public ProductRepositoryTests(DatabaseFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { } [Fact] public void ProductsAreSeeded() { var repo = Host.Services.GetRequiredService(); Assert.NotEmpty(repo.GetAll()); } } ``` -------------------------------- ### Write Dependency Injection Tests Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Shows how to test services registered with dependency injection using Codebelt's ManagedHostFixture and HostTest. ```csharp using Codebelt.Extensions.Xunit.Hosting; using Microsoft.Extensions.DependencyInjection; using Xunit; public class ServiceFixture : ManagedHostFixture { } public class ServiceTests : HostTest { public ServiceTests(ServiceFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); } [Fact] public void ServiceIsRegistered() { var service = Host.Services.GetRequiredService(); Assert.NotNull(service); } } ``` -------------------------------- ### Run all tests Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Execute all tests within the project. This is the most basic command for initiating a test run. ```bash dotnet test ``` -------------------------------- ### InMemoryTestStore() Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Initializes a new empty in-memory store. ```APIDOC ## InMemoryTestStore() ### Description Initializes a new empty in-memory store. ### Method Constructor ### Parameters None ``` -------------------------------- ### Write ASP.NET Core Tests Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Illustrates testing ASP.NET Core applications, including service configuration and endpoint testing, using Codebelt's ManagedWebHostFixture and WebHostTest. ```csharp using Codebelt.Extensions.Xunit.Hosting.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Xunit; public class WebFixture : ManagedWebHostFixture { } public class WebTests : WebHostTest { public WebTests(WebFixture fixture, ITestOutputHelper output) : base(fixture, output) { } public override void ConfigureServices(IServiceCollection services) { services.AddScoped(); } public override void ConfigureApplication(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapGet("/api/weather", WeatherHandler); }); } [Fact] public async Task ApiReturnsWeather() { var client = new HttpClient { BaseAddress = new Uri("http://localhost") }; var response = await client.GetAsync("/api/weather"); Assert.True(response.IsSuccessStatusCode); } private static IResult WeatherHandler() { return Results.Ok(new { temp = 72 }); } } ``` -------------------------------- ### Import Individual Packages Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Use this XML snippet to add individual Codebelt.Extensions.Xunit packages to your project's dependencies. ```xml ``` -------------------------------- ### ASP.NET Core Using Statement Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/package-overview.md Import the namespace for ASP.NET Core specific features within Codebelt.Extensions.Xunit. ```csharp // ASP.NET Core using Codebelt.Extensions.Xunit.Hosting.AspNetCore; ``` -------------------------------- ### Test Application Logging with InMemoryTestStore Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-store.md Demonstrates how to use `InMemoryTestStore` to capture log entries within an xUnit test. Ensure `XunitTestLoggerEntry` is defined for log entry records. ```csharp using Xunit; using Microsoft.Extensions.Logging; [Fact] public void TestApplicationLogging() { var store = new InMemoryTestStore(); var logger = LoggerFactory.Create(builder => { builder.AddProvider(new CustomLoggerProvider(store)); }).CreateLogger("TestCategory"); logger.LogInformation("Test started"); logger.LogError("An error occurred"); Assert.Equal(2, store.Count); } ``` -------------------------------- ### Restore packages Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Restore all NuGet packages required by the solution. This command should be run before building. ```bash dotnet restore Codebelt.Extensions.Xunit.slnx ``` -------------------------------- ### Integration Testing with Test Server in C# Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md Set up a full-stack integration test for a web application using a managed web host. Configure real services and define API endpoints for testing. ```csharp public class IntegrationTestFixture : ManagedWebHostFixture { public IntegrationTestFixture() { ConfigureServicesCallback = services => { // Real services for integration testing services.AddScoped(); services.AddScoped(); services.AddDbContext(); services.AddXunitTestLogging(LogLevel.Information); }; } } public class OrderApiIntegrationTests : WebHostTest { private readonly HttpClient _client; public OrderApiIntegrationTests(IntegrationTestFixture fixture, ITestOutputHelper output) : base(fixture, output) { _client = new HttpClient { BaseAddress = new Uri("http://localhost") }; } public override void ConfigureServices(IServiceCollection services) { } public override void ConfigureApplication(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapPost("/orders", CreateOrderHandler); endpoints.MapGet("/orders/{id}", GetOrderHandler); }); } [Fact] public async Task CreateAndRetrieveOrder() { // Create order var createRequest = new { customerId = 1, amount = 99.99 }; var createResponse = await _client.PostAsJsonAsync("/orders", createRequest); Assert.True(createResponse.IsSuccessStatusCode); var order = await createResponse.Content.ReadAsAsync(); // Retrieve order var getResponse = await _client.GetAsync($"/orders/{order.Id}"); Assert.Equal(System.Net.HttpStatusCode.OK, getResponse.StatusCode); var retrieved = await getResponse.Content.ReadAsAsync(); Assert.Equal(order.Id, retrieved.Id); Assert.Equal(99.99, retrieved.Amount); } private static IResult CreateOrderHandler(CreateOrderRequest request, IOrderService service) { var order = service.Create(request.CustomerId, request.Amount); return Results.Ok(order); } private static IResult GetOrderHandler(int id, IOrderService service) { var order = service.Get(id); return order != null ? Results.Ok(order) : Results.NotFound(); } } public record CreateOrderRequest(int CustomerId, decimal Amount); public record Order(int Id, int CustomerId, decimal Amount); ``` -------------------------------- ### Pack NuGet packages Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Pack the project into NuGet packages. This command is typically used after a successful release build. ```bash dotnet pack -c Release ``` -------------------------------- ### IHostTest Interface Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Contract for test classes requiring bare-bone dependency injection support. ```APIDOC ## Interface IHostTest **Namespace:** `Codebelt.Extensions.Xunit.Hosting` ### Description Contract for test classes requiring bare-bone dependency injection support. ### Members #### Properties - **Host** (`IHost`) - Required - The configured host instance ``` -------------------------------- ### IWebApplicationFixture Interface for Testing ASP.NET Core Applications Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Fixture interface for testing existing ASP.NET Core applications using their entry point. It allows customization of the `IWebHostBuilder` and provides access to the `TestServer` for in-process HTTP server testing. ```csharp public interface IWebApplicationFixture : IHostFixture where TEntryPoint : class { Action ConfigureWebHostCallback { get; set; } TestServer Server { get; } void ConfigureHost(Test hostTest); } ``` -------------------------------- ### HostTest Constructor with Generic Host Fixture Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-tests.md Initializes the test with a generic host fixture. Requires an implementation of IGenericHostFixture. Optional parameters include xUnit's ITestOutputHelper and the caller's Type. ```csharp protected HostTest(T hostFixture, ITestOutputHelper output = null, Type callerType = null) : this(false, hostFixture, output, callerType) ``` -------------------------------- ### InitializeAsync Method Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/test-base-class.md Handles asynchronous initialization tasks immediately after the test class instance is created and before the test method executes. ```APIDOC ## InitializeAsync Method ### Description Handles asynchronous initialization tasks immediately after the test class instance is created and before the test method executes. Implements xUnit's `IAsyncLifetime.InitializeAsync()`. ### Method Signature `public virtual ValueTask InitializeAsync()` ### Return Type `ValueTask` — Return `default` if no async initialization is needed. ### Remarks This method supports xUnit's async fixture initialization pattern. ``` -------------------------------- ### IWebApplicationFixture Interface Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/aspnetcore-hosting.md Fixture interface for testing existing ASP.NET Core applications using their entry point. ```APIDOC ## IWebApplicationFixture Interface **Namespace:** `Codebelt.Extensions.Xunit.Hosting.AspNetCore` **Location:** `src/Codebelt.Extensions.Xunit.Hosting.AspNetCore/IWebApplicationFixture.cs` ```csharp public interface IWebApplicationFixture : IHostFixture where TEntryPoint : class { Action ConfigureWebHostCallback { get; set; } TestServer Server { get; } void ConfigureHost(Test hostTest); } ``` **Type Parameter:** `TEntryPoint` — A type in the entry point assembly of the application ### Members | Member | Type | Description | |--------|------|-------------| | ConfigureWebHostCallback | `Action?` | Delegate to customize the IWebHostBuilder | | Server | `TestServer` | The ASP.NET Core TestServer instance | | ConfigureHost(Test) | method | Creates and configures the IHost | **Remarks:** `TestServer` provides an in-process HTTP server for testing the application. ``` -------------------------------- ### Configure XUnit Test Logging with ITestOutputHelperAccessor Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/logging-utilities.md Enables async-aware logging by registering ITestOutputHelperAccessor. Logging will automatically utilize the current asynchronous context's output helper. ```csharp public override void ConfigureServices(IServiceCollection services) { // Register accessor services.AddXunitTestLoggingOutputHelperAccessor(); // Logging automatically uses current async context's output services.AddXunitTestLogging(); } ``` -------------------------------- ### Build with skipped assembly signing Source: https://github.com/codebeltnet/xunit/blob/main/AGENTS.md Build the project while skipping assembly signing. This is useful for CI environments or external contributors. ```bash dotnet build -p:SkipSignAssembly=true ``` -------------------------------- ### Basic Unit Test with Output Capture in C# Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/common-patterns.md Use this pattern for simple unit tests that require writing debug output. Ensure the test class inherits from `Codebelt.Extensions.Xunit.Test` and injects `ITestOutputHelper` into the constructor. ```csharp using Codebelt.Extensions.Xunit; using Xunit; public class StringUtilityTests : Test { public StringUtilityTests(ITestOutputHelper output) : base(output) { } [Fact] public void TrimAndNormalize() { var input = " hello world "; var expected = "hello world"; TestOutput?.WriteLines( $"Input: '{input}'", $"Expected: '{expected}'", $"Has output: {HasTestOutput}" ); var result = input.Trim(); Assert.Equal(expected, result); } [Fact] public void WildcardMatching() { // Test wildcard string comparison Assert.True(Test.Match("Hello*World", "Hello Beautiful World")); Assert.True(Test.Match("*.txt", "readme.txt")); Assert.False(Test.Match("exact", "inexact")); } } ``` -------------------------------- ### TestOutputHelperAccessor Constructor Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/extensions-and-utilities.md Initializes the TestOutputHelperAccessor with an optional ITestOutputHelper. ```APIDOC ## TestOutputHelperAccessor(ITestOutputHelper output = null) ### Description Initializes the accessor with an optional ITestOutputHelper. ### Parameters #### Path Parameters - **output** (ITestOutputHelper?) - Optional - The test output helper to set ``` -------------------------------- ### Customize WebHostBuilder Configuration Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/configuration.md Customize the IWebHostBuilder used to bootstrap an ASP.NET Core application. This is useful for adding configuration sources. ```csharp configureWebHostCallback = builder => { builder.ConfigureAppConfiguration(config => { config.AddInMemoryCollection(new Dictionary { ["TestSettings:Timeout"] = "100" }); }); }; ``` -------------------------------- ### WebMinimalHostTest Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-index.md Test base class for minimal ASP.NET Core host applications. Designed for testing lightweight minimal API applications. ```APIDOC ## Class WebMinimalHostTest ### Description Test base for minimal host web apps. ### Purpose Test base for minimal host web applications. ``` -------------------------------- ### HostFixture Abstract Class Source: https://github.com/codebeltnet/xunit/blob/main/_autodocs/api-reference/hosting-fixtures.md The HostFixture abstract class implements IHostFixture and IAsyncLifetime, offering core fixture functionality with lifecycle hooks, thread-safe disposal, and asynchronous host startup. ```APIDOC ## HostFixture Abstract Class **Namespace:** `Codebelt.Extensions.Xunit.Hosting` **Location:** `src/Codebelt.Extensions.Xunit.Hosting/HostFixture.cs` ### Summary Abstract base class implementing `IHostFixture` and `IAsyncLifetime`. Provides core fixture functionality with lifecycle hooks, thread-safe disposal, and async host startup. ### Properties #### Host ```csharp public IHost Host { get; protected set; } ``` The initialized IHost instance for dependency injection. #### Configuration ```csharp public IConfiguration Configuration { get; protected set; } ``` The IConfiguration extracted from the IHost. #### Environment ```csharp public IHostEnvironment Environment { get; protected set; } ``` The IHostEnvironment extracted from the IHost. #### ConfigureCallback ```csharp public Action ConfigureCallback { get; set; } ``` Delegate invoked with initialized configuration and environment. #### AsyncHostRunnerCallback ```csharp protected Func AsyncHostRunnerCallback { get; set; } ``` Delegate responsible for starting the host. Default implementation handles synchronization context to prevent deadlocks on single-CPU VMs. #### Disposed ```csharp public bool Disposed { get; } ``` Indicates whether this fixture has been disposed. ### Methods #### HasTypes(Type type, params Type[] types) ```csharp protected static bool HasTypes(Type type, params Type[] types) ``` Determines whether a type contains one or more of the specified target types, checking the type hierarchy and generic type definitions. | Parameter | Type | Description | |-----------|------|-------------| | type | `Type` | The type to validate | | types | `Type[]` | Target types to match against | **Return Type:** `bool` — true if type contains any of the target types. #### OnDisposeManagedResources() ```csharp protected virtual void OnDisposeManagedResources() ``` Called during disposal to clean up the Host. #### OnDisposeManagedResourcesAsync() ```csharp protected virtual ValueTask OnDisposeManagedResourcesAsync() ``` Called during async disposal. On .NET 9+, properly disposes IAsyncDisposable hosts. #### OnDisposeUnmanagedResources() ```csharp protected virtual void OnDisposeUnmanagedResources() ``` Hook for unmanaged resource cleanup. #### Dispose() ```csharp public void Dispose() ``` Thread-safe synchronous disposal with double-check locking. #### Dispose(bool disposing) ```csharp protected void Dispose(bool disposing) ``` Protected disposal implementation called by Dispose() and DisposeAsync(). #### DisposeAsync() ```csharp public async ValueTask DisposeAsync() ``` Asynchronously disposes the host and resources. #### InitializeAsync() ```csharp public virtual ValueTask InitializeAsync() ``` Called by xUnit before tests run. Override to perform async initialization. ```