https://github.com/pengweiqhca/Xunit.DependencyInjection
Use Microsoft.Extensions.DependencyInjection to resolve xUnit test cases.
https://github.com/pengweiqhca/Xunit.DependencyInjection
ioc xunit
Last synced: 11 months ago
JSON representation
Use Microsoft.Extensions.DependencyInjection to resolve xUnit test cases.
- Host: GitHub
- URL: https://github.com/pengweiqhca/Xunit.DependencyInjection
- Owner: pengweiqhca
- License: mit
- Created: 2018-02-06T09:36:52.000Z (about 8 years ago)
- Default Branch: main
- Last Pushed: 2025-04-22T03:52:53.000Z (11 months ago)
- Last Synced: 2025-04-22T05:18:44.047Z (11 months ago)
- Topics: ioc, xunit
- Language: C#
- Homepage:
- Size: 553 KB
- Stars: 391
- Watchers: 9
- Forks: 53
- Open Issues: 12
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Use `Microsoft.Extensions.DependencyInjection` to resolve xUnit test cases
> XUnit v2 users: please use [v2](https://github.com/pengweiqhca/Xunit.DependencyInjection/tree/v2) branch, Xunit.DependencyInjection.xRetry depend on upstream packages, waiting for update.
> Xunit.DependencyInjection.SkippableFact are obsoleted on xunit.v3.
## How to use
Install the [Nuget](https://www.nuget.org/packages/Xunit.DependencyInjection) package.
```sh
dotnet add package Xunit.DependencyInjection
```
In your testing project, add the following framework
```cs
namespace Your.Test.Project
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient();
}
}
}
```
Example test `class`.
```cs
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.DependencyInjection` is built into the generic host and fully supports its lifecycle, allowing you to use all features supported by the generic host, including but not limited to `IHostedService`.
## Integration asp.net core TestHost(3.0+)
### Asp.Net Core Startup
```sh
dotnet add package Microsoft.AspNetCore.TestHost
```
```C#
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureWebHost[Defaults](webHostBuilder => webHostBuilder
.UseTestServer(options => options.PreserveExecutionContext = true)
.UseStartup());
}
```
### MinimalApi
If you use MinimalApi rather than asp.net core Startup class.
Add package reference for `Xunit.DependencyInjection.AspNetCoreTesting`
```sh
dotnet add package Xunit.DependencyInjection.AspNetCoreTesting
```
```C#
public class Startup
{
public IHostBuilder CreateHostBuilder() => MinimalApiHostBuilderFactory.GetHostBuilder();
}
```
> Maybe your asp.net core project should InternalsVisibleTo or add `public partial class Program {}` in the end of `Program.cs`;
>
> Detail see [Xunit.DependencyInjection.Test.AspNetCore](https://github.com/pengweiqhca/Xunit.DependencyInjection/tree/main/test/Xunit.DependencyInjection.Test.AspNetCore)
## `Startup` limitation
`Startup` supports two configuration styles, and the `Configure` method is supported by both.
### HostApplicationBuilder-style
* `ConfigureHostApplicationBuilder` method (distinguish by this method)
``` C#
public void ConfigureHostApplicationBuilder(IHostApplicationBuilder hostApplicationBuilder) { }
```
* `BuildHostApplicationBuilder` method
> **NOTE**: If this method signature is not found, the host is built by simply calling `hostApplicationBuilder.Build();`.
``` C#
public IHost BuildHostApplicationBuilder(HostApplicationBuilder hostApplicationBuilder)
{
return hostApplicationBuilder.Build();
}
```
### Startup-style
* `CreateHostBuilder` method
``` C#
public class Startup
{
public IHostBuilder CreateHostBuilder([AssemblyName assemblyName]) { }
}
```
* `ConfigureHost` method
```C#
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) { }
}
```
* `ConfigureServices` method
```C#
public class Startup
{
public void ConfigureServices(IServiceCollection services[, HostBuilderContext context]) { }
}
```
* `BuildHost` method
> **NOTE**: If this method signature is not found, the host is built by simply calling `hostBuilder.Build();`.
```C#
public class Startup
{
public IHost BuildHost([IHostBuilder hostBuilder]) { return hostBuilder.Build(); }
}
```
## How to find `Startup`?
### 1. Specific startup
Declare [Startup] on test class
### 2. Nested startup
```C#
public class TestClass1
{
public class Startup
{
public void ConfigureServices(IServiceCollection services) { }
}
```
### 3. Closest startup
If the class type full name is "A.B.C.TestClass", find Startup in the following order:
1. `A.B.C.Startup`
2. `A.B.Startup`
3. `A.Startup`
4. `Startup`
### 4. Default startup
> Default startup is required before 8.7.0, is optional in some case after 8.7.0.
>
> If is required, please add a startup class in your test project.
Default is find `Your.Test.Project.Startup, Your.Test.Project`.
If you want to use a special `Startup`, you can define `XunitStartupAssembly` and `XunitStartupFullName` in the `PropertyGroup` section
```xml
Abc
Xyz
```
| XunitStartupAssembly | XunitStartupFullName | Startup |
| -------------------- | -------------------- | -------------------------------------------- |
| | | Your.Test.Project.Startup, Your.Test.Project |
| Abc | | Abc.Startup, Abc |
| | Xyz | Xyz, Your.Test.Project |
| Abc | Xyz | Xyz, Abc |
## Parallel
By default, xUnit runs all test cases in a test class synchronously. This package can extend the test framework to execute tests in parallel.
```xml
```
This package has two policies to run test cases in parallel.
1. Enhance or true
Respect xunit [parallelization](https://xunit.net/docs/running-tests-in-parallel) behavior.
2. Force
Ignore xunit [parallelization](https://xunit.net/docs/running-tests-in-parallel) behavior and force running tests in parallel.
If [`[Collection]`](https://github.com/xunit/xunit/issues/1227#issuecomment-297131879)(if ParallelizationMode is not `Force`), `[CollectionDefinition(DisableParallelization = true)]`, `[DisableParallelization]` declared on the test class, the test class will run sequentially. If `[DisableParallelization]`, `[MemberData(DisableDiscoveryEnumeration = true)]` declared on the test method, the test method will run sequentially.
**It is recommended to use xunit 2.8.0+ and without setting `parallelAlgorithm`**
> Thanks [Meziantou.Xunit.ParallelTestFramework](https://github.com/meziantou/Meziantou.Xunit.ParallelTestFramework)
## How to disable Xunit.DependencyInjection
```xml
false
```
## How to inject ITestOutputHelper
```C#
internal class DependencyClass : IDependency
{
private readonly ITestOutputHelperAccessor _testOutputHelperAccessor;
public DependencyClass(ITestOutputHelperAccessor testOutputHelperAccessor)
{
_testOutputHelperAccessor = testOutputHelperAccessor;
}
}
```
## Write `Microsoft.Extensions.Logging` to `ITestOutputHelper`
Add package reference for `Xunit.DependencyInjection.Logging`
```sh
dotnet add package Xunit.DependencyInjection.Logging
```
> The call chain must be from the test case. If not, this feature will not work.
```C#
public class Startup
{
public void ConfigureServices(IServiceCollection services) => services
.AddLogging(lb => lb.AddXunitOutput());
}
```
## How to inject `IConfiguration` or `IHostEnvironment` into `Startup`?
```C#
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureServices((context, services) => { context.XXXX });
}
```
or
```C#
public class Startup
{
public void ConfigureServices(IServiceCollection services, HostBuilderContext context)
{
context.XXXX;
}
}
```
## How to configure `IConfiguration`?
```C#
public class Startup
{
public void ConfigureHost(IHostBuilder hostBuilder) => hostBuilder
.ConfigureHostConfiguration(builder => { })
.ConfigureAppConfiguration((context, builder) => { });
}
```
## [MemberData] how to inject?
Use **[MethodData]**
## Integrate OpenTelemetry
```C#
TracerProviderBuilder builder;
builder.AddSource("Xunit.DependencyInjection");
```
## Do something before and after test case
Inherit `BeforeAfterTest` and register as `BeforeAfterTest` service.
[See demo](https://github.com/pengweiqhca/Xunit.DependencyInjection/blob/main/test/Xunit.DependencyInjection.Test/BeforeAfterTestTest.cs#13).
## Initialize some data on startup.
If it is synchronous initialization, you can use the `Configure` method. If it is asynchronous initialization, you should use `IHostedService`.