https://github.com/metacoder-feff/feff.testfixtures
Replace setup/teardown methods with reusable Fixtures
https://github.com/metacoder-feff/feff.testfixtures
dotnet fixtures testing
Last synced: 2 months ago
JSON representation
Replace setup/teardown methods with reusable Fixtures
- Host: GitHub
- URL: https://github.com/metacoder-feff/feff.testfixtures
- Owner: metacoder-feff
- License: mit
- Created: 2026-03-05T17:43:33.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-22T19:20:40.000Z (3 months ago)
- Last Synced: 2026-04-22T21:24:42.857Z (3 months ago)
- Topics: dotnet, fixtures, testing
- Language: C#
- Homepage:
- Size: 294 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# FEFF.TestFixtures
[](https://github.com/metacoder-feff/FEFF.TestFixtures/actions/workflows/test.yml)
[](https://github.com/metacoder-feff/FEFF.TestFixtures/actions/workflows/release-nuget.yml)
Integrations:
[](https://www.nuget.org/packages/FEFF.TestFixtures.XunitV3)
[](https://www.nuget.org/packages/FEFF.TestFixtures.TUnit)
Fixture libraries:
[](https://www.nuget.org/packages/FEFF.TestFixtures)
[](https://www.nuget.org/packages/FEFF.TestFixtures.AspNetCore)
[](https://www.nuget.org/packages/FEFF.TestFixtures.AspNetCore.EF)
[](https://www.nuget.org/packages/FEFF.TestFixtures.AspNetCore.SignalR)
✅ Replace setup/teardown methods and test-class "Disposable pattern" with reusable **Fixtures**.
✅ Fixtures can depend on other fixtures.
✅ Fixtures can be configured via standard IServiceProvider.
✅ Set of fixtures to simplify testing AspNetCore applications [see full AspNetCore example](https://github.com/metacoder-feff/FEFF.TestFixtures/blob/main/examples/ExampleTests.AspNetCore/ApiTests.cs).
[Fixture list](#fixture-list)
[Full Documentation](https://metacoder-feff.github.io/FEFF.TestFixtures/)
## Prerequisites
+ .NET 8.0 or later
+ Test framework: xUnit v3 **or** TUnit
+ For ASP.NET Core fixtures: ASP.NET Core 8.0 or later
## Getting started (Xunit.V3)
Add a library reference to a test project:
```bash
dotnet add package FEFF.TestFixtures.XunitV3
```
Add an assembly-level attribute to initialize the extension:
```csharp
[assembly: FEFF.TestFixtures.Xunit.TestFixturesExtension]
```
Use the `TestContext.Current.GetFeffFixture()` extension method to get the required fixture instance at any point during a test:
```csharp
public class SystemUnderTest
{
public static void Write(string filePath) =>
File.WriteAllText(filePath, "some-data", Encoding.UTF8);
}
public class ExampleTests
{
protected TmpDirectoryFixture TmpDir { get; } = TestContext.Current.GetFeffFixture();
[Fact]
public void File__should_be_created()
{
// Arrange
var filePath = TmpDir.Path + "/file.tmp";
File.Exists(filePath).Should().BeFalse();
// Act
SystemUnderTest.Write(filePath);
// Assert
File.Exists(filePath)
.Should().BeTrue();
File.ReadAllText(filePath, Encoding.UTF8)
.Should().Be("some-data");
}
}
```
In this example, `TmpDir` is created when the fixture is first requested in the test class constructor. The **scope** of the fixture in this example is `test-case`.
The `TmpDir` and its contents are automatically deleted after the test finishes.\
This example uses [AwesomeAssertions](https://github.com/AwesomeAssertions/AwesomeAssertions) for the `Should()` assertion DSL.\
See the [source code for this example](https://github.com/metacoder-feff/FEFF.TestFixtures/blob/main/examples/ExampleTests.XunitV3/ExampleTests.cs).
### Defining other scopes for a fixture
The scope of a fixture is defined by the test creator using an overloaded method:
```csharp
TestContext.Current.GetFeffFixture(FixtureScopeType scopeType)
```
Also note that multiple instances of the fixture can exist in different scopes if needed.
### Creating a fixture
Just create a class with the `FixtureAttribute`.
Let's examine the source code for the `TmpDirectoryFixture` we used above.
```csharp
[Fixture]
public sealed class TmpDirectoryFixture : IDisposable
{
public string Path { get; } = Directory.CreateTempSubdirectory().FullName;
public void Dispose()
{
// double dispose guard
try
{
Directory.Delete(Path, true);
}
catch (DirectoryNotFoundException)
{
}
}
}
```
### Fixture Dependencies
Fixtures can depend on other fixtures. Dependencies are injected via the constructor:
```csharp
[Fixture]
public class MyCustomFixture1
{
}
[Fixture]
public class MyCustomFixture2
{
}
[Fixture]
public record MyFixtureSet(
MyCustomFixture1 F1,
MyCustomFixture2 F2,
);
public class ExampleTests
{
protected MyFixtureSet Set { get; } = TestContext.Current.GetFeffFixture();
//...
}
```
Note:
+ All fixture dependencies (`MyCustomFixture1` and `MyCustomFixture2`) exist in the same scope as the dependent fixture (`MyFixtureSet` in the example above).
+ Fixtures cannot have cyclic dependencies.
## Fixture List
### FEFF.TestFixtures Library
+ EnvironmentFixture
+ Snapshots the process environment and restores it after a test (the test scope)
+ TmpDirectoryFixture
+ Creates a unique directory and removes it along with its contents after a test (the test scope)
+ Can optionally skip deletion
+ TmpScopeIdFixture
+ Generates a string that is unique for each scope (e.g., for each test)
### FEFF.TestFixtures.AspNetCore Fixture Library
[See usage examples](https://github.com/metacoder-feff/FEFF.TestFixtures/blob/main/examples/ExampleTests.AspNetCore/ApiTests.cs)
+ AppManagerFixture
+ Starts and stops the application via TestHost
+ Allows modification of Configuration/ServiceCollection before the application starts
+ AppClientFixture
+ Creates and disposes an HttpClient for testing
+ AppServicesFixture
+ Provides access to the application's service provider in the test context
+ Creates and disposes ServiceScope
+ FakeLoggerFixture
+ Adds FakeLoggerProvider to the application under test
+ Provides access to the application's logs in the test context
+ FakeTimeFixture
+ Replaces TimeProvider with FakeTimeProvider
+ Provides an ability to manipulate application's time
+ FakeRandomFixture
+ Replaces Random with FakeRandom
+ Provides an ability to manipulate random values that application receives
+ TmpDatabaseNameFixture
+ Updates connection strings to use a unique database name for test isolation
### FEFF.TestFixtures.AspNetCore.EF Fixture Library
+ DatabaseLifecycleFixture
+ Removes the database at the end of the fixture scope (e.g., after a test) (DbContext.EnsureDeleted)
+ Can optionally create database at any time of the test (DbContext.EnsureCreated)
### [FEFF.TestFixtures.AspNetCore-Preview]
+ AuthorizedAppClientFixture
+ Creates and disposes an authenticated HttpClient for testing
+ The user must provide a valid JWT
+ SignalrClientFixture
+ Creates and disposes a SignalR client for testing
+ Fixture provides awaitable events for server messages
+ The user must provide a path to the SignalR Hub within the tested API
+ The user can optionally provide a JWT to authenticate the SignalR client
### Development in Progress
The following fixtures are planned but not yet implemented:
+ A unique Redis key prefix for test isolation
+ A unique S3 path prefix for test isolation
+ Fake outbound HTTP connection to stub integrations with third-party APIs
[Full Documentation](https://metacoder-feff.github.io/FEFF.TestFixtures/)