Xunit.DependencyInjection 11.3.2
Xunit.DependencyInjection
Use Microsoft.Extensions.DependencyInjection to resolve xUnit test cases: constructor-inject services into your test classes instead of writing them by hand, and reuse the same Startup/host configuration you use in your application.
xUnit v2 users: please use the v2 branch.
Xunit.DependencyInjection.SkippableFactis obsolete on xunit.v3 and no longer needed.
Getting started
Install the NuGet package:
dotnet add package Xunit.DependencyInjection
Add a Startup class to your test project and register your services in ConfigureServices:
namespace Your.Test.Project
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<IDependency, DependencyClass>();
}
}
}
Then inject IDependency into your test class constructor, exactly like you would with any other DI-enabled class:
public interface IDependency
{
int Value { get; }
}
internal class DependencyClass : IDependency
{
public int Value => 1;
}
public class MyAwesomeTests
{
private readonly IDependency _d;
public MyAwesomeTests(IDependency d) => _d = d;
[Fact]
public void AssertThatWeDoStuff()
{
Assert.Equal(1, _d.Value);
}
}
Xunit.DependencyInjectionbuilds on top of the generic host and fully supports its lifecycle, so you can use any feature the generic host offers, including (but not limited to)IHostedService.
Integrating with ASP.NET Core TestHost (3.0+)
With an ASP.NET Core Startup class
dotnet add package Microsoft.AspNetCore.TestHost
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureWebHost[Defaults](webHostBuilder => webHostBuilder
.UseTestServer(options => options.PreserveExecutionContext = true)
.UseStartup<AspNetCoreStartup>());
}
With Minimal APIs
If your web project uses Minimal APIs instead of an ASP.NET Core Startup class, install Xunit.DependencyInjection.AspNetCoreTesting:
dotnet add package Xunit.DependencyInjection.AspNetCoreTesting
public class Startup
{
public IHostBuilder CreateHostBuilder() => MinimalApiHostBuilderFactory.GetHostBuilder<Program>();
}
Your ASP.NET Core project may need to add
InternalsVisibleTofor the test project, or addpublic partial class Program { }at the end ofProgram.cs, so the test project can referenceProgram.See Xunit.DependencyInjection.Test.AspNetCore for a full example.
Startup configuration styles
Startup supports two configuration styles. The Configure method (see Initializing data on startup) is supported by both styles.
HostApplicationBuilder style
CreateHostApplicationBuildermethodIf this method is not found, the host falls back to
Host.CreateEmptyApplicationBuilder(new() { ApplicationName = assemblyName.Name }).public HostApplicationBuilder CreateHostApplicationBuilder([AssemblyName assemblyName]) { }ConfigureHostApplicationBuildermethod (presence of this method selects theHostApplicationBuilderstyle)public void ConfigureHostApplicationBuilder(IHostApplicationBuilder hostApplicationBuilder) { }BuildHostApplicationBuildermethodIf this method is not found, the host is built by simply calling
hostApplicationBuilder.Build().public IHost BuildHostApplicationBuilder(HostApplicationBuilder hostApplicationBuilder) { return hostApplicationBuilder.Build(); }
Startup/HostBuilder style
CreateHostBuildermethodpublic class Startup { public IHostBuilder CreateHostBuilder([AssemblyName assemblyName]) { } }ConfigureHostmethodpublic class Startup { public void ConfigureHost(IHostBuilder hostBuilder) { } }ConfigureServicesmethodpublic class Startup { public void ConfigureServices(IServiceCollection services[, HostBuilderContext context]) { } }BuildHostmethodIf this method is not found, the host is built by simply calling
hostBuilder.Build().public class Startup { public IHost BuildHost([IHostBuilder hostBuilder]) { return hostBuilder.Build(); } }
Method parameters wrapped in [...] above are optional.
How is Startup located?
Startup classes are looked up in the following order; the first match wins.
1. Startup declared on the test class
Apply [Startup(typeof(MyStartup))] on the test class.
2. Nested Startup
public class TestClass1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services) { }
}
}
3. Closest Startup in the namespace hierarchy
If the test class's full name is A.B.C.TestClass, Startup is looked up in this order:
A.B.C.StartupA.B.StartupA.StartupStartup
4. Default Startup
A default
Startupwas required before 8.7.0, and is optional in some cases after 8.7.0. When it's required, add a startup class to your test project as shown above.
By default, Your.Test.Project.Startup, Your.Test.Project is used.
If you want to use a custom Startup, set XunitStartupAssembly and/or XunitStartupFullName in your project's PropertyGroup:
<Project>
<PropertyGroup>
<XunitStartupAssembly>Abc</XunitStartupAssembly>
<XunitStartupFullName>Xyz</XunitStartupFullName>
</PropertyGroup>
</Project>
| XunitStartupAssembly | XunitStartupFullName | Resulting Startup |
|---|---|---|
Your.Test.Project.Startup, Your.Test.Project |
||
Abc |
Abc.Startup, Abc |
|
Xyz |
Xyz, Your.Test.Project |
|
Abc |
Xyz |
Xyz, Abc |
Running tests in parallel
By default, xUnit runs all test cases within a test class synchronously. This package extends the test framework so tests can run in parallel.
If you register a custom
ITestCollectionOrderer, test collections run in the order it specifies, which can be slower than running without one.
Enable it with the ParallelizationMode MSBuild property:
<Project>
<PropertyGroup>
<ParallelizationMode></ParallelizationMode>
</PropertyGroup>
</Project>
This package supports two parallelization policies:
Enhance(ortrue)Respects xUnit's own parallelization behavior.
ForceIgnores xUnit's parallelization behavior and forces tests to run in parallel.
A test class runs sequentially when it's decorated with [Collection] (unless ParallelizationMode is Force), [CollectionDefinition(DisableParallelization = true)], or [DisableParallelization]. A test method runs sequentially when it's decorated with [DisableParallelization] or [MemberData(DisableDiscoveryEnumeration = true)].
We recommend leaving parallelAlgorithm unset.
Thanks to Meziantou.Xunit.ParallelTestFramework for the inspiration.
Disabling Xunit.DependencyInjection
<Project>
<PropertyGroup>
<EnableXunitDependencyInjectionDefaultTestFrameworkAttribute>false</EnableXunitDependencyInjectionDefaultTestFrameworkAttribute>
</PropertyGroup>
</Project>
Injecting ITestOutputHelper
Inject ITestOutputHelperAccessor instead of ITestOutputHelper directly, since the actual instance is only available while a test is running:
internal class DependencyClass : IDependency
{
private readonly ITestOutputHelperAccessor _testOutputHelperAccessor;
public DependencyClass(ITestOutputHelperAccessor testOutputHelperAccessor)
{
_testOutputHelperAccessor = testOutputHelperAccessor;
}
}
Writing Microsoft.Extensions.Logging output to ITestOutputHelper
Install Xunit.DependencyInjection.Logging:
dotnet add package Xunit.DependencyInjection.Logging
The call chain must originate from the running test case; otherwise this feature won't work.
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services
.AddLogging(lb => lb.AddXunitOutput());
}
Injecting IConfiguration or IHostEnvironment into Startup
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureServices((context, services) => { /* use context.Configuration / context.HostingEnvironment */ });
}
or
public class Startup
{
public void ConfigureServices(IServiceCollection services, HostBuilderContext context)
{
// use context.Configuration / context.HostingEnvironment
}
}
Customizing IConfiguration
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureHostConfiguration(builder => { })
.ConfigureAppConfiguration((context, builder) => { });
}
How do I inject values with [MemberData]?
[MemberData] members are static and can't be resolved from the container, so use [MethodData] instead — it resolves the referenced method's parameters from DI.
Integrating with OpenTelemetry
Register the Xunit.DependencyInjection activity source with your TracerProviderBuilder to capture the spans this library emits:
TracerProviderBuilder builder;
builder.AddSource("Xunit.DependencyInjection");
Running code before and after each test
Inherit from BeforeAfterTest and register your implementation as a BeforeAfterTest service.
Initializing data on startup
For synchronous initialization, use the Configure method. For asynchronous initialization, use an IHostedService.
Related packages
| Package | Description |
|---|---|
| Xunit.DependencyInjection.Logging | Write Microsoft.Extensions.Logging output to ITestOutputHelper, see above |
| Xunit.DependencyInjection.AspNetCoreTesting | Integration with ASP.NET Core Minimal API TestHost, see above |
| Xunit.DependencyInjection.StaFact | Run [StaFact]/[StaTheory] test cases on an STA thread (e.g. for UI tests) |
| Xunit.DependencyInjection.xRetry | Support xRetry's [RetryFact]/[RetryTheory] |
| Xunit.DependencyInjection.FsCheck | Support FsCheck property-based [Property] tests |
| Xunit.DependencyInjection.Demystifier | Use Ben.Demystifier to format exception stack traces |
| Xunit.DependencyInjection.Analyzer | Roslyn analyzer that validates Startup class shape at compile time |
| Xunit.DependencyInjection.Template | dotnet new xunit-di template to scaffold a new test project |
StaFact
dotnet add package Xunit.DependencyInjection.StaFact
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services.AddStaFactSupport();
}
public class MyStaTests
{
[StaFact]
public void RunOnStaThread() { }
[StaTheory]
[InlineData(1)]
public void RunOnStaThread(int value) { }
}
xRetry
dotnet add package Xunit.DependencyInjection.xRetry
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services.AddXRetrySupport();
}
public class MyRetryTests
{
[RetryFact(3)]
public void FlakyTest() { }
}
FsCheck
dotnet add package Xunit.DependencyInjection.FsCheck
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services.AddFsCheckSupport();
}
Demystifier
dotnet add package Xunit.DependencyInjection.Demystifier
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services.UseDemystifyExceptionFilter();
}
Analyzer
The analyzer is automatically added as an analyzer reference when you install Xunit.DependencyInjection, and reports compile-time diagnostics (e.g. multiple Startup constructors, invalid Configure* method signatures) so misconfigured Startup classes are caught early.
Project template
dotnet new install Xunit.DependencyInjection.Template
dotnet new create xunit-di -n MyTestProject
See Xunit.DependencyInjection.Template for details.
No packages depend on Xunit.DependencyInjection.
Use Microsoft.Extensions.DependencyInjection to inject xunit testclass. If you want write Microsoft.Extensions.Logging to ITestOutputHelper, please install Xunit.DependencyInjection.Logging.
Release notes:
11.3: Support FsCheck.Xunit.v3. 11.2: Update xunit.v3 to 3.2.2, Move HostManager.Start/Stop to AssemblyRunner. 11.1: Update xunit.v3 to 3.2.0. 11.0: C# 14, Downgrade Microsoft.Extensions.Hosting to 8.0. 10.8: Add CreateHostApplicationBuilder method. 10.7: Update xunit.v3 to 3.0.1, does not set ApplicationName if it is already configured. 10.6: Update xunit.v3 to 3.0.0. 10.5: Improve compatibility with top level statements. 10.4: Fix #146. 10.3: Update xunit.v3 to 2.0.0. 10.2: Fix some parallelization problem. 10.1: Allow the default startup to be missing anywhere. 10.0: Upgrade xunit to v3.
.NET Framework 4.7.2
- Microsoft.Extensions.Hosting (>= 8.0.0)
- System.Diagnostics.DiagnosticSource (>= 9.0.0)
- xunit.v3.extensibility.core (>= 3.2.2 && < 4.0.0)
.NET 8.0
- Microsoft.Extensions.Hosting (>= 8.0.0)
- System.Diagnostics.DiagnosticSource (>= 9.0.0)
- xunit.v3.extensibility.core (>= 3.2.2 && < 4.0.0)
| Version | Downloads | Last updated |
|---|---|---|
| 12.0.1 | 15 | 08/25/2026 |
| 12.0.0 | 15 | 08/22/2026 |
| 11.3.2 | 13 | 08/22/2026 |
| 11.3.1 | 14 | 08/13/2026 |
| 11.3.0 | 21 | 06/14/2026 |
| 11.2.1 | 28 | 03/26/2026 |
| 11.2.0 | 25 | 03/26/2026 |
| 11.1.1 | 24 | 03/26/2026 |
| 11.1.0 | 29 | 03/26/2026 |
| 11.0.0 | 27 | 03/26/2026 |
| 10.8.0 | 23 | 03/26/2026 |
| 10.7.0 | 25 | 03/26/2026 |
| 10.6.0 | 25 | 03/26/2026 |
| 10.5.0 | 28 | 03/26/2026 |
| 10.4.2 | 25 | 03/26/2026 |
| 10.4.1 | 26 | 03/26/2026 |
| 10.4.0 | 26 | 03/26/2026 |
| 10.3.0 | 26 | 03/26/2026 |
| 10.2.1 | 26 | 03/26/2026 |
| 10.2.0 | 27 | 03/26/2026 |
| 10.1.1 | 21 | 03/26/2026 |
| 10.1.0 | 26 | 03/26/2026 |
| 10.0.0 | 31 | 03/26/2026 |
| 9.9.2 | 25 | 03/26/2026 |
| 9.9.1 | 25 | 03/26/2026 |
| 9.9.0 | 25 | 03/26/2026 |
| 9.8.0 | 27 | 03/26/2026 |
| 9.7.1 | 28 | 03/26/2026 |
| 9.7.0 | 25 | 03/26/2026 |
| 9.6.0 | 29 | 03/26/2026 |
| 9.5.0 | 25 | 03/26/2026 |
| 9.4.0 | 27 | 03/26/2026 |
| 9.3.1 | 26 | 03/26/2026 |
| 9.3.0 | 26 | 03/26/2026 |
| 9.2.1 | 25 | 03/26/2026 |
| 9.1.0 | 26 | 03/26/2026 |
| 9.0.1 | 23 | 03/26/2026 |
| 8.9.1 | 23 | 03/26/2026 |
| 8.9.0 | 22 | 03/26/2026 |
| 8.8.2 | 27 | 03/26/2026 |
| 8.8.1 | 28 | 03/26/2026 |
| 8.7.2 | 30 | 03/26/2026 |
| 8.7.1 | 27 | 03/26/2026 |
| 8.7.0 | 29 | 03/26/2026 |
| 8.6.1 | 22 | 03/26/2026 |
| 8.6.0 | 24 | 03/26/2026 |
| 8.5.0 | 27 | 03/25/2026 |
| 8.4.1 | 22 | 03/26/2026 |
| 8.4.0 | 27 | 03/26/2026 |
| 8.3.0 | 29 | 03/26/2026 |
| 8.2.0 | 25 | 03/26/2026 |
| 8.1.0 | 30 | 03/26/2026 |
| 8.0.0 | 28 | 03/26/2026 |
| 7.7.0 | 18 | 03/26/2026 |
| 7.6.0 | 25 | 03/26/2026 |
| 7.5.1 | 24 | 03/26/2026 |
| 7.4.0 | 26 | 03/26/2026 |
| 7.3.0 | 24 | 03/26/2026 |
| 7.2.0 | 26 | 03/26/2026 |
| 7.1.0 | 27 | 03/26/2026 |