XUnit.Hosting
3.0.2
See the version list below for details.
dotnet add package XUnit.Hosting --version 3.0.2
NuGet\Install-Package XUnit.Hosting -Version 3.0.2
<PackageReference Include="XUnit.Hosting" Version="3.0.2" />
<PackageVersion Include="XUnit.Hosting" Version="3.0.2" />
<PackageReference Include="XUnit.Hosting" />
paket add XUnit.Hosting --version 3.0.2
#r "nuget: XUnit.Hosting, 3.0.2"
#:package XUnit.Hosting@3.0.2
#addin nuget:?package=XUnit.Hosting&version=3.0.2
#tool nuget:?package=XUnit.Hosting&version=3.0.2
XUnit.Hosting
A testing library that integrates Microsoft.Extensions.Hosting with xUnit v3, enabling dependency injection, configuration management, and hosted services in your unit tests.
Features
- Host Builder Integration - Leverage
HostApplicationBuilderin your xUnit tests - Dependency Injection - Full support for Microsoft.Extensions.DependencyInjection
- Configuration Management - Use appsettings.json, user secrets, and other configuration providers
- Memory Logger - Built-in in-memory logging provider for test verification
- Collection Fixtures - Share application host across multiple tests
Installation
dotnet add package XUnit.Hosting
Quick Start
1. Create a Test Fixture
Create a fixture that inherits from TestApplicationFixture and configure your application services:
public class MyTestFixture : TestApplicationFixture
{
protected override void ConfigureApplication(HostApplicationBuilder builder)
{
base.ConfigureApplication(builder);
// Add configuration
builder.Configuration.AddUserSecrets<MyTestFixture>();
// Register services
builder.Services.AddSingleton<IMyService, MyService>();
// Add hosted services
builder.Services.AddHostedService<MyBackgroundService>();
}
}
2. Define a Collection
Create a collection definition to share the fixture across tests:
// support capturing console and trace output in xunit v3
[assembly: CaptureConsole]
[assembly: CaptureTrace]
[CollectionDefinition(CollectionName)]
public class MyTestCollection : ICollectionFixture<MyTestFixture>
{
public const string CollectionName = nameof(MyTestCollection);
}
3. Write Your Tests
[Collection(MyTestCollection.CollectionName)]
public class ServiceTests : TestHostBase<MyTestFixture>
{
public ServiceTests(MyTestFixture fixture) : base(fixture)
{
}
[Fact]
public void TestMyService()
{
// Arrange - Get service from DI container
var service = Services.GetRequiredService<IMyService>();
// Act
var result = service.DoSomething();
// Assert
Assert.NotNull(result);
}
[Fact]
public void TestConfiguration()
{
// Access configuration
var config = Services.GetRequiredService<IConfiguration>();
var value = config["MyKey"];
Assert.NotNull(value);
}
}
Core Components
TestApplicationFixture
Abstract base class for creating test fixtures with host support. This class implements ITestHostFixture and IDisposable, providing lazy initialization of the host to ensure it's only created when first accessed.
Key Properties:
Host- The IHost instance (lazily initialized and automatically started)Services- IServiceProvider for dependency resolution
Methods to Override:
ConfigureApplication(HostApplicationBuilder builder)- Configure services, logging, and configuration. The default implementation sets the minimum log level toLogLevel.Debugand configures console logging with scopes for detailed test diagnostics.CreateBuilderSettings()- Customize host builder settings such as environment name, application name, or content root path. Returnsnullby default to use default settings.CreateHost()- Override host creation logic for advanced scenarios. The default implementation creates settings, builds the host, and starts it automatically.
TestHostBase<TFixture>
Base class for test classes that provides convenient access to the hosted test environment. This class implements IDisposable for proper cleanup of test resources.
Properties:
OutputHelper- ITestOutputHelper? for writing diagnostic output to the current testTestContext- ITestContext providing access to test metadata and stateFixture- Access to the shared test fixture (TFixture instance)Services- IServiceProvider for resolving services (convenience property forFixture.Services)
ITestHostFixture
Interface that defines the contract for XUnit collection fixtures providing access to a configured host and dependency injection container.
Properties:
Host- The IHost instance configured and started for the test collectionServices- IServiceProvider for dependency resolution (typically equivalent toHost.Services)
Memory Logger
XUnit.Hosting includes a built-in in-memory logger for capturing and asserting log output in tests.
Setup
public class MyTestFixture : TestApplicationFixture
{
protected override void ConfigureApplication(HostApplicationBuilder builder)
{
base.ConfigureApplication(builder);
// Add memory logger (registered as singleton in DI)
builder.Logging.AddMemoryLogger();
// Or with settings
builder.Logging.AddMemoryLogger(settings =>
{
settings.MinimumLevel = LogLevel.Information;
settings.Capacity = 2048;
settings.Filter = (category, level) => level >= LogLevel.Warning;
});
}
}
Usage in Tests
[Collection(MyTestCollection.CollectionName)]
public class LoggingTests(MyTestFixture fixture) : TestHostBase<MyTestFixture>(fixture)
{
[Fact]
public void MemoryLogger()
{
var logger = Services.GetRequiredService<ILogger<LoggingTests>>();
Assert.NotNull(logger);
logger.LogInformation("This is a test log message.");
// Retrieve the MemoryLoggerProvider to access the logs
var memoryLoggerProvider = Services.GetRequiredService<MemoryLoggerProvider>();
Assert.NotNull(memoryLoggerProvider);
// Verify that the log message was captured
var logs = memoryLoggerProvider.Logs();
Assert.Contains(logs, log => log.Message.Contains("This is a test log message."));
// Filter by category
var categoryLogs = memoryLoggerProvider.Logs("XUnit.Hosting.Tests.LoggingTests");
Assert.NotEmpty(categoryLogs);
// Filter by log level
var infoLogs = memoryLoggerProvider.Logs(LogLevel.Information);
Assert.NotEmpty(infoLogs);
}
}
MemoryLoggerSettings
Configure the memory logger with these options:
MinimumLevel- Minimum log level to capture (default:LogLevel.Debug)Capacity- Maximum number of log entries to keep (default: 1024)Filter- Custom filter function for fine-grained control
MemoryLogEntry
Log entries captured include:
Timestamp- DateTime when the log entry was createdLogLevel- The log level of the entry (Trace, Debug, Information, Warning, Error, Critical)EventId- Event identifier associated with the log entryCategory- Category name of the logger that created this entryMessage- Formatted log messageException- Exception associated with the log entry, if any (nullable)State- The state object passed to the logger (nullable)Scopes- Read-only collection of scope values that were active when the log entry was created
Integration Testing with Docker Databases
XUnit.Hosting works seamlessly with Testcontainers to provide isolated database environments for integration tests. This approach uses IAsyncLifetime to manage container lifecycle and IHostedService to seed the database.
Install Testcontainers
dotnet add package Testcontainers.MsSql
Create a Database Fixture with Testcontainers
public class DatabaseFixture : TestApplicationFixture, IAsyncLifetime
{
private readonly MsSqlContainer _msSqlContainer = new MsSqlBuilder()
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
.WithPassword("P@ssw0rd123!")
.Build();
public async ValueTask InitializeAsync()
{
await _msSqlContainer.StartAsync();
}
public async ValueTask DisposeAsync()
{
await _msSqlContainer.DisposeAsync();
}
protected override void ConfigureApplication(HostApplicationBuilder builder)
{
base.ConfigureApplication(builder);
// Change database from container default
var connectionBuilder = new SqlConnectionStringBuilder(_msSqlContainer.GetConnectionString());
connectionBuilder.InitialCatalog = "SampleDataDocker";
// Register DbContext with container connection string
builder.Services.AddDbContext<SampleDataContext>(options =>
options.UseSqlServer(connectionBuilder.ToString())
);
// Register database seeding hosted service
builder.Services.AddHostedService<DatabaseInitialize>();
}
}
Create a Database Seeder with IHostedService
public class DatabaseInitialize : IHostedService
{
private readonly ILogger<DatabaseInitialize> _logger;
private readonly SampleDataContext _dataContext;
public DatabaseInitialize(ILogger<DatabaseInitialize> logger, SampleDataContext dataContext)
{
_logger = logger;
_dataContext = dataContext;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Initialize Database StartAsync()");
// Ensure database is created and apply migrations
await _dataContext.Database.EnsureCreatedAsync(cancellationToken);
// Or use migrations: await _dataContext.Database.MigrateAsync(cancellationToken);
// Seed test data
_dataContext.Users.AddRange(
new User { Name = "Test User 1", Email = "user1@test.com" },
new User { Name = "Test User 2", Email = "user2@test.com" }
);
await _dataContext.SaveChangesAsync(cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Initialize Database StopAsync()");
return Task.CompletedTask;
}
}
Define the Collection
// Support capturing console and trace output
[assembly: CaptureConsole]
[assembly: CaptureTrace]
[CollectionDefinition(CollectionName)]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{
public const string CollectionName = nameof(DatabaseCollection);
}
Write Database Tests
[Collection(DatabaseCollection.CollectionName)]
public class DatabaseTests : TestHostBase<DatabaseFixture>
{
public DatabaseTests(DatabaseFixture fixture) : base(fixture)
{
}
[Fact]
public async Task GetUser_WithValidId_ReturnsUser()
{
// Arrange
var dbContext = Services.GetRequiredService<SampleDataContext>();
// Act
var user = await dbContext.Users.FindAsync([1], TestContext.CancellationToken);
// Assert
Assert.NotNull(user);
Assert.Equal("Test User 1", user.Name);
Assert.Equal("user1@test.com", user.Email);
}
[Fact]
public async Task GetAllUsers_ReturnsSeededUsers()
{
// Arrange
var dbContext = Services.GetRequiredService<SampleDataContext>();
// Act
var users = await dbContext.Users.ToListAsync(TestContext.CancellationToken);
// Assert
Assert.True(users.Count >= 2);
}
}
Best Practices
- Share Expensive Resources - Use collection fixtures to share database connections, HTTP clients, etc.
- Clear State Between Tests - Reset or clear shared resources in test constructors if needed
- Use Memory Logger - Verify logging behavior in your tests
- Keep Fixtures Focused - Create separate fixtures for different test scenarios
- Leverage Configuration - Use user secrets and environment variables for test configuration
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.Extensions.Hosting (>= 9.0.10)
- xunit.v3.extensibility.core (>= 3.1.0)
-
net8.0
- Microsoft.Extensions.Hosting (>= 9.0.10)
- xunit.v3.extensibility.core (>= 3.1.0)
-
net9.0
- Microsoft.Extensions.Hosting (>= 9.0.10)
- xunit.v3.extensibility.core (>= 3.1.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories (1)
Showing the top 1 popular GitHub repositories that depend on XUnit.Hosting:
| Repository | Stars |
|---|---|
|
loresoft/Injectio
Source generator that helps register attribute marked services in the dependency injection ServiceCollection
|
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.0 | 6,757 | 11/12/2025 |
| 3.1.0 | 524 | 11/7/2025 |
| 3.0.2 | 808 | 10/15/2025 |
| 3.0.1 | 446 | 10/15/2025 |
| 3.0.0 | 456 | 10/15/2025 |
| 2.0.1 | 1,978 | 6/3/2025 |
| 2.0.0 | 3,221 | 11/13/2024 |
| 1.7.2 | 614 | 10/27/2024 |
| 1.7.1 | 1,391 | 7/26/2024 |
| 1.7.0 | 1,642 | 5/10/2024 |
| 1.6.0 | 689 | 5/4/2024 |
| 1.5.0 | 1,143 | 3/20/2024 |
| 1.2.0 | 744 | 12/21/2023 |
| 1.1.0 | 534 | 11/21/2023 |
| 1.0.0 | 700 | 9/7/2023 |
| 1.0.0-beta.2 | 189 | 9/7/2023 |
| 1.0.0-beta.1 | 161 | 9/7/2023 |