Jds.TestingUtils.Xunit2.Extras
0.2.0
dotnet add package Jds.TestingUtils.Xunit2.Extras --version 0.2.0
NuGet\Install-Package Jds.TestingUtils.Xunit2.Extras -Version 0.2.0
<PackageReference Include="Jds.TestingUtils.Xunit2.Extras" Version="0.2.0" />
paket add Jds.TestingUtils.Xunit2.Extras --version 0.2.0
#r "nuget: Jds.TestingUtils.Xunit2.Extras, 0.2.0"
// Install Jds.TestingUtils.Xunit2.Extras as a Cake Addin #addin nuget:?package=Jds.TestingUtils.Xunit2.Extras&version=0.2.0 // Install Jds.TestingUtils.Xunit2.Extras as a Cake Tool #tool nuget:?package=Jds.TestingUtils.Xunit2.Extras&version=0.2.0
TestingUtils.Xunit.Extras (NuGet) (GitHub)
This library supplements xUnit
. Specifically, it adds pattern interface
s, structured test class
es and source generators.
How To Use
Add the NuGet package to your xUnit test project. (Currently only xUnit 2 is supported.)
Test Class with Structured Execution/Initialization Steps
In this scenario the execution/initialization steps occur once for each test (assertion) method.
In this scenario, the goal is to add one or more structured steps to a test (assertion) class. These steps are expected to be completed before any of the test (assertion) methods. Additionally, the steps might require async
work.
To Implement Test Class with Structured Execution/Initialization Steps
Create a normal xUnit test class and either inherit from Jds.TestingUtils.Xunit2.Extras.BaseCaseFixture
or, if you need to inherit from another type, implement Jds.TestingUtils.Xunit2.Extras.ICaseArrangementFixture
.
When inheriting from BaseCaseFixture
there are protected
methods to override
(ArrangeAsync
, ActAsync
, etc.). Override any (or none) to support your needed arrangement.
When implementing ICaseArrangementFixture
all structured test case phases (ICasePhases
) have a default implementation provided by the interface. Implement any or all of the following: ICasePhases.ArrangeAsync
, ICasePhases.AcquireSanityValuesAsync
, ICasePhases.ActAsync
, ICasePhases.AcquireVerificationValuesAsync
. If the test requires any cleanup (e.g., deleting temporary database resources, files), implement IDestructiveCase.CleanupAsync
.
See example ExampleTestClassWithRepeatedInitialization
implementation.
Test Class with Single-Invocation Execution/Initialization
In this scenario the execution/initialization steps only occur once, irrespective of how many test (assertion) methods are invoked against it.
In this scenario, the goal is to add one or more structured steps to a test case fixture class
. These steps are expected to be completed before any of the test (assertion) methods. Additionally, the steps might require async
work.
The basic idea in this scenario is that the "case fixture" is created by xUnit. As usual the "case assertion" class (test class) is constructed once for each test (assertion) method. However, in this scenario the case assertion class receives the case fixture from xUnit during construction. The same fixture class instance is used when constructing the test class for each assertion method.
This pattern is useful for ASP.NET Core integration tests and other scenarios where you need to perform some work (such as an
async
web API request) and make multiple assertions (within distinct test methods) upon the same output, e.g., assert upon theHttpStatusCode
separately from headers' content and response body.
To Implement Test Class with Single-Invocation Execution/Initialization
Create a "case fixture" class which inherits from Jds.TestingUtils.Xunit2.Extras.BaseCaseFixture
. Create a test "assertion" class which inherits from Jds.TestingUtils.Xunit2.Extras.BaseCaseAssertions<TCaseArrangementFixture>
(where TCaseArrangementFixture
is your case fixture class which inherited BaseCaseFixture
).
When inheriting from BaseCaseFixture
there are protected
methods to override
(ArrangeAsync
, ActAsync
, etc.). Override any (or none) to support your needed arrangement.
Add assertions (i.e., [Fact]
and [Theory]
methods) to the "assertion" class.
See example ExampleComplexTest
implementation.
Shared Case Context/Configuration across Multiple Test Cases
In this scenario, the goal is to create a "context" value object (e.g., to contain shared configuration) which will be passed to multiple test case fixture class
es, facilitating coordinated tests.
Important: This pattern assumes that your "context" is essentially read-only after construction. It is not advised to mutate or add data in the "context" to avoid unexpected results.
The basic idea in this scenario is that you design a context value object to hold the shared configuration. During test execution xUnit will construct an instance and pass it to all the associated case fixture classes. Each case fixture is intended to perform a single logical test "case" arrangement, which will occur prior to all test assertions. The same instance of the context is passed to every case fixture. Further, the same case fixture instance is passed to every related "assertion" class.
Without this library, this is a complicated situation to arrange, due to the limits of xUnit test class dependency injection. Implementation normally requires creating an xUnit
ICollectionFixture
(including[CollectionDefinition]
attribute), a base case fixture class with reliable constructor signature, and a base test case assertion class which both usesIClassFixture<>
and has a compatible constructor signature—all while placing[Collection]
attributes on the correct classes to enable xUnit dependency injection.This pattern is particularly useful in ASP.NET Core integration test projects. It enables things like establishing a "context" object with shared application configuration (e.g., Entity Framework connection strings, validation options) and consistently using those values which are expected to be stable for the life of the "context". The authors have frequently used this pattern with generated data to enable verifying that side effects (like logging or external API requests) are invoked using values from the application's
IConfiguration
.
To Implement Shared Case Context/Configuration across Multiple Test Cases
Create a shared case context class
with a parameterless constructor. (Parameterless constructor is very important for xUnit.) Apply the [Jds.TestingUtils.Xunit2.Extras.SharedCaseContext]
attribute to the class. This will trigger source generation (during compile), which creates new classes in your assembly which use your shared case context. Specifically, it creates a {YourContextName}Fixture
base fixture class, a {YourContextName}Assertions
class, and the additional classes and configuration needed to support xUnit dependency injection.
After the shared case context is created:
To create a "Test Class with Structured Execution/Initialization Steps" (see above) which uses the shared case context, just create a new test fixture which inherits from {YourContextName}Fixture
. Access the shared context object via its .Context
property.
To create a "Test Class with Single-Invocation Execution/Initialization" (see above) which uses the shared case context, create a new test case fixture which inherits from {YourContextName}Fixture
and implement any test case phase methods needed. Then, create a test assertion class which inherits from {YourContextName}Assertions<TCaseFixture>
, where TCaseFixture
is the class you just created which inherited {YourContextName}Fixture
.
See example SharedContextExample
implementation.
API Documentation
Jds.TestingUtils.Xunit2.Extras
namespace
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | 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. |
-
net8.0
- Microsoft.CodeAnalysis.CSharp (>= 4.7.0)
- xunit.abstractions (>= 2.0.3)
- xunit.extensibility.core (>= 2.4.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
0.2.0 | 108 | 11/12/2024 | |
0.1.0 | 91 | 11/11/2024 | |
0.1.0-build-20241108-032815... | 82 | 11/8/2024 | |
0.1.0-build-20241107-135359... | 67 | 11/7/2024 | |
0.1.0-build-20241106-055637... | 70 | 11/6/2024 | |
0.1.0-build-20241105-034723... | 74 | 11/5/2024 | |
0.1.0-build-20241104-054537... | 67 | 11/4/2024 |