- Home
- .NET tutorials
- xUnit v3 update: Ability to skip tests & a new TestContext
xUnit v3 update: Ability to skip tests & a new TestContext
Published: Monday 20 October 2025
xUnit 3 has been released with new assert methods and a new TestContext
. Here is how you use it.
Supported frameworks
xUnit 3 is supported on the following frameworks:
- .NET 8 (or later)
- .NET Framework 4.7.2 (or later)
If you are on a version that is below .NET 8, you will have to stay with xUnit 2 until you update.
Creating an xUnit 3 project
You'll need to install the xUnit 3 templates to be able to create a new xUnit 3 project. You can do that by running this command line:
dotnet new install xunit.v3.templates
Once installed, you can create a new xUnit 3 project. You do that by calling:
dotnet new xunit3
Create a new xUnit 3 project in Visual Studio
When you install the xUnit 3 templates, you'll be able to create a project in Visual Studio.
Do a search for xUnit v3 Test and select the template.

Create a new xUnit 3 project in Visual Studio
Set the project name, location, solution name and framework to create the project.
Update an existing project
You'll need to remove the xunit NuGet package. You can do that by opening up the .csproj
file of your xUnit test project and remove the PackageReference
to that NuGet package.
With that removed, you'll need to add the xunit.v3 package and update xunit.runner.visualstudio. In Visual Studio 2022, go to Tools, NuGet Package Manager and Manage NuGet Packages for Solution.... Do a search for both xunit.v3 and xunit.runner.studio and install both packages to your xUnit project.

Add new xUnit projects to your xUnit project
To check that the update has been successful, open up Test Explorer by going to Test and Text Explorer. If the tests run, then the update has been completed.
New assert methods for skipping tests
xUnit 3 provides new assert methods for skipping tests. We have written some unit tests with this method:
// SpeedConversionHelper.cs
public class SpeedConversionHelper
{
public static decimal ConvertToKph(decimal mph)
{
return mph * 1.6093m;
}
}
Skipping tests in xUnit 2 was somewhat limited. You could only skip tests by adding the Skip
attribute in either the Fact
or Theory
attributes:
// SpeedConversionHelperSkipTests.cs
public class SpeedConversionHelperSkipTests
{
[Fact(Skip = "The act is more than 160 kph")]
public void ConvertToKph_IfOver160Kph_SkipTestInAttribute()
{
var act = SpeedConversionHelper.ConvertToKph(100);
Assert.Equal(160.93m, act);
}
}
But that has been significantly improved with xUnit 3. When Assert.Skip
is called, it skips the test completely and allows you to add a reason. There are two other skip methods that allow you to add a condition on skipping a test. Assert.SkipWhen
will skip the test if the condition is true and Assert.SkipUnless
will skip it when it's false.
In the following unit tests, we are skipping the tests if the conversion is over 160 kph:
// SpeedConversionHelperSkipTests.cs
public class SpeedConversionHelperSkipTests
{
[Theory]
[InlineData(50, 80.465)]
[InlineData(75, 120.6975)]
[InlineData(100, 160.93)]
public void ConvertToKph_IfOver160Kph_SkipTest(decimal mph, decimal expectedKph)
{
var act = SpeedConversionHelper.ConvertToKph(mph);
if (act > 160)
{
Assert.Skip("The act is more than 160 kph");
}
Assert.Equal(expectedKph, act);
}
[Theory]
[InlineData(50, 80.465)]
[InlineData(75, 120.6975)]
[InlineData(100, 160.93)]
public void ConvertToKph_IfOver160Kph_SkipWhenTest(decimal mph, decimal expectedKph)
{
var act = SpeedConversionHelper.ConvertToKph(mph);
Assert.SkipWhen(act > 160, "The act is more than 160 kph");
Assert.Equal(expectedKph, act);
}
[Theory]
[InlineData(50, 80.465)]
[InlineData(75, 120.6975)]
[InlineData(100, 160.93)]
public void ConvertToKph_IfOver160Kph_SkipUnlessTest(decimal mph, decimal expectedKph)
{
var act = SpeedConversionHelper.ConvertToKph(mph);
Assert.SkipUnless(act <= 160, "The act is more than 160 kph");
Assert.Equal(expectedKph, act);
}
}
Additional skip properties in Fact
and Theory
There are also additional skip properties when using the Fact
or Theory
attribute. You can use a static property in your test class and it to the SkipWhen
and SkipUnless
properties in the Fact
and Theory
attributes.
In this example, we've added a Debug
property and set it to true if the tests are run in debug mode and set it to false for the opposite. We've then used the SkipWhen
and SkipUnless
to add the Debug
property as a string using the nameof
expression:
// SpeedConversionHelperSkipAttributeTests.cs
public class SpeedConversionHelperSkipAttributeTests
{
#if DEBUG
public static bool Debug => true;
#else
public static bool Debug => false;
#endif
[Fact(Skip = "In debug", SkipWhen = nameof(Debug))]
public void ConvertToKph_InDebug_SkipTest()
{
var act = SpeedConversionHelper.ConvertToKph(100);
Assert.Equal(160.93m, act);
}
[Fact(Skip = "Not in debug", SkipUnless = nameof(Debug))]
public void ConvertToKph_NotInDebug_SkipTest()
{
var act = SpeedConversionHelper.ConvertToKph(100);
Assert.Equal(160.93m, act);
}
}
You can also use a static property from another class by using the SkipType
property. Here, we've added a TestProperties
class and set the DebugMode
property to true if it's in debug, whilst setting it to false if the opposite applies.
We then used the SkipType
and the typeof
expression to get the class:
// SpeedConversionHelperSkipAttributeTests.cs
public class SpeedConversionHelperSkipAttributeTests
{
[Fact(Skip = "In debug", SkipWhen = "DebugMode", SkipType = typeof(TestProperties))]
public void ConvertToKph_InDebugFromAnotherType_SkipTest()
{
var act = SpeedConversionHelper.ConvertToKph(100);
Assert.Equal(160.93m, act);
}
}
public class TestProperties
{
#if DEBUG
public static bool DebugMode => true;
#else
public static bool DebugMode => false;
#endif
}
TheoryDataRow
type
xUnit 3 has introduced the TheoryDataRow
type. It's a class that represents a single row of theory data and allows you to provide strongly typed parameters for attributes in your Theory
test. It's used as an alternative to providing plain arrays and objects:
// SpeedConversionHelperTheoryDataRowTests.cs
public class SpeedConversionHelperTheoryDataRowTests
{
public static IEnumerable<TheoryDataRow<decimal, decimal>> TestData =
[new(50m, 80.465m), new(75m, 120.6975m), new(100m, 160.93m)];
[Theory]
[MemberData(nameof(TestData))]
public void ConvertToKph_WithMph_CheckCorrectKph(decimal mph, decimal expectedKph)
{
var act = SpeedConversionHelper.ConvertToKph(mph);
Assert.Equal(expectedKph, act);
}
}
Matrix theory data
The new MatrixTheoryData
class allows you to can combine between 2 and 5 sets of data in a matrix to generate theory data.
Consider a list of mph
decimal
values that are 50 and 100 and a list of attempt
int
values that are 1, 2 and 3.
This would create the following parameters for your Theory
test:
mph = 50, attempt = 1
mph = 50, attempt = 2
mph = 50, attempt = 3
mph = 100, attempt = 1
mph = 100, attempt = 2
mph = 100, attempt = 3
And this is how you can use it in a unit test:
// SpeedConversionHelperMatrixTheoryDataTests.cs
public class SpeedConversionHelperMatrixTheoryDataTests
{
public static TheoryData<decimal, int> TestData =
new MatrixTheoryData<decimal, int>(
[50m, 100m],
[1, 2, 3]
);
[Theory]
[MemberData(nameof(TestData))]
public void ConvertToKph_KphIsOver50_ReturnsTrue(decimal mph, int attempt)
{
if (attempt >= 3)
{
Assert.Skip("Do not run on the third attempt or beyond");
}
var act = SpeedConversionHelper.ConvertToKph(mph);
Assert.True(act >= 50);
}
}
Test context
A new TestContext
class has been added. This allows you to get and set information about the current state of the test pipeline.
This example shows adding a warning if the conversion to kph is over 160. The warning also provides information about the test being run:
// SpeedConversionHelperTestContextTests.cs
public class SpeedConversionHelperTestContextTests
{
public static IEnumerable<TheoryDataRow<decimal, decimal>> TestData =
[new(50m, 80.465m), new(75m, 120.6975m), new(100m, 160.93m)];
[Theory]
[MemberData(nameof(TestData))]
public void ConvertToKph_WithMph_CheckCorrectKph(decimal mph, decimal expectedKph)
{
var act = SpeedConversionHelper.ConvertToKph(mph);
if (act > 160)
{
TestContext.Current.AddWarning("${TestContext.Current.TestMethod} - The act is more than 160 kph");
}
Assert.Equal(expectedKph, act);
}
}
Watch the video
You'll learn more about the new features included in xUnit 3 when you watch this video:
And you can download the code example if you want to try these for yourself.
More xUnit 3 features
We've covered some of the top new features. If you want a more in-depth list, xUnit have provided a full list of what's new in xUnit 3. This includes how to override the culture as well as other miscellaneous changes.
Related tutorials

Use ASP.NET Core's TestServer in xUnit to test Web API endpoints: TestServer - Part 1
Configure an instance of WebHostBuilder and use it in ASP.NET Core's TestServer to test Web API endpoints in an xUnit test project.