JestDotnet 2.2.0
See the version list below for details.
dotnet add package JestDotnet --version 2.2.0
NuGet\Install-Package JestDotnet -Version 2.2.0
<PackageReference Include="JestDotnet" Version="2.2.0" />
<PackageVersion Include="JestDotnet" Version="2.2.0" />
<PackageReference Include="JestDotnet" />
paket add JestDotnet --version 2.2.0
#r "nuget: JestDotnet, 2.2.0"
#:package JestDotnet@2.2.0
#addin nuget:?package=JestDotnet&version=2.2.0
#tool nuget:?package=JestDotnet&version=2.2.0
Jest Snapshot Dotnet
Simple snapshot testing with inspiration from amazing Jest library.
Installation
You can install it using NuGet.
dotnet add package JestDotnet
Supported frameworks
| Target | Version |
|---|---|
| .NET | 10.0 |
How it works
If you are unfamiliar with snapshot testing, I recommend you to check Jest documentation.
This library works very similarly. When you run ShouldMatchSnapshot for the first time, it will generate JSON snapshot of the serialization of the object.
If you run it second time, it will check if the JSON serialization of the object is the same as the saved JSON snapshot.
It is important to commit snapshots with your code to the git.
Updating snapshots
You can mass update snapshot (useful when you add new property to an object, change default value or remove a property).
Simply set environment variable UPDATE to true and run the tests that you want to update. It will update all snapshots that have failed.
UPDATE=true dotnet test
If you are using JetBrains Rider, go to Settings -> Build, Execution, Deployment -> Unit Testing -> Test Runner and set it there.
Remember to unset the variable again.
Continuous Integration
Snapshots are not created if you are running tests inside Continuous Integration environment (GitHub Actions, GitLab CI, Jenkins, Teamcity, Azure/AWS Pipelines etc.).
Library detects CI environment by checking the CI environment variable. If it is set to true, test fails if snapshot is missing.
API
Extension methods
ShouldMatchSnapshot
public static void ShouldMatchSnapshot(this object actual, string hint = "");
Example
var person = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
person.ShouldMatchSnapshot();
ShouldMatchInlineSnapshot
public static void ShouldMatchInlineSnapshot(this object actual, string inlineSnapshot);
Example
var person = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
person.ShouldMatchInlineSnapshot(@"
{
""FirstName"": ""John"",
""LastName"": ""Bam"",
""DateOfBirth"": ""2008-07-07T00:00:00"",
""Age"": 13,
}"
);
ShouldMatchObject
public static void ShouldMatchObject(this object actual, object expected);
Example
var actual = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
var expected = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
actual.ShouldMatchObject(expected);
Static methods
If you don't like extension methods, you can use static class JestAssert
ShouldMatchSnapshot
public static void ShouldMatchSnapshot(object actual, string hint = "");
Example
var person = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
JestAssert.ShouldMatchSnapshot(person);
ShouldMatchInlineSnapshot
public static void ShouldMatchInlineSnapshot(object actual, string inlineSnapshot);
Example
var person = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
JestAssert.ShouldMatchInlineSnapshot(person, @"
{
""FirstName"": ""John"",
""LastName"": ""Bam"",
""DateOfBirth"": ""2008-07-07T00:00:00"",
""Age"": 13,
}"
);
ShouldMatchObject
public static void ShouldMatchObject(object actual, object expected);
Example
var actual = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
var expected = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
JestAssert.ShouldMatchObject(actual, expected);
Advanced
Excluding properties
If you want to exclude some properties from the diff, you can use SnapshotSettings class to specify your own
- diffing options (use
SnapshotSettings.CreateDiffOptions)
Example:
SnapshotSettings.CreateDiffOptions = () => new JsonDiffOptions
{
PropertyFilter = (s, context) => s != "LastName"
};
or pass JsonDiffOptions as optional argument
var actual = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
var expected = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = ""
};
// this does not throw an exception and the test completes successfully
// property "LastName" is ignored from the diff
JestAssert.ShouldMatchObject(actual, expected, new JsonDiffOptions
{
PropertyFilter = (s, context) => s != "LastName"
});
Configuring directory and file extensions
If you need to configure it, you can use SnapshotSettings class to specify your own
- extension instead of
.snap(useSnapshotSettings.SnapshotExtension) - directory instead of
__snapshots__(useSnapshotSettings.SnapshotDirectory) - function that generates directory, extension and filename (use
SnapshotSettings.CreatePath)
Popular use is to change directory of the snapshot files. You can do it like this:
SnapshotSettings.SnapshotDirectory = "__custom__";
var testObject = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
JestAssert.ShouldMatchSnapshot(testObject);
// you can return it back using
SnapshotSettings.SnapshotDirectory = SnapshotSettings.DefaultSnapshotDirectory;
Configuring serialization
For serialization, System.Text.Json is used. By default, snapshots are written with indented formatting and non-ASCII characters are preserved as literal UTF-8 (using JavaScriptEncoder.Create(UnicodeRanges.All)).
If you need to configure it, you can use SnapshotSettings class to specify your own
JsonSerializerOptions(useSnapshotSettings.CreateSerializerOptions)
Change line endings to LF
Popular use is to change line ending of the .snap files. For example if you want to set line ending to Linux LF, you can do it like this:
SnapshotSettings.NewLine = "\n";
var testObject = new Person
{
Age = 13,
DateOfBirth = new DateTime(2008, 7, 7),
FirstName = "John",
LastName = "Bam"
};
JestAssert.ShouldMatchSnapshot(testObject);
Sorting
Properties are sorted alphabetically by default using ordinal string comparison (AlphabeticalSortModifier.SortProperties). This ensures deterministic, culture-independent snapshot output regardless of property declaration order.
Note: When overriding
CreateSerializerOptions, includeAlphabeticalSortModifier.SortPropertiesin yourTypeInfoResolvermodifiers to keep the default sorting behavior. Also includeEncoder = JavaScriptEncoder.Create(UnicodeRanges.All)to keep non-ASCII characters readable andReferenceHandler = ReferenceHandler.IgnoreCyclesto handle circular references.
Circular references
Circular references are handled by default via ReferenceHandler.IgnoreCycles — cyclic references are serialized as null instead of throwing.
Using Newtonsoft.Json types
If your codebase uses Newtonsoft.Json types (JObject, JArray, JToken), System.Text.Json cannot serialize them correctly out of the box. Register pre-serializers to handle them:
// In test setup or assembly initializer
SnapshotSettings.AddPreSerializer<JObject>(obj => obj.ToString());
SnapshotSettings.AddPreSerializer<JArray>(obj => obj.ToString());
Then snapshot testing works as expected:
var json = JObject.Parse("{\"name\": \"Alice\", \"age\": 30}");
json.ShouldMatchSnapshot();
Custom type serialization (pre-serializers)
The pre-serializer hook is not limited to Newtonsoft — you can register a custom serializer for any type that System.Text.Json cannot handle:
SnapshotSettings.AddPreSerializer<MyCustomType>(obj => obj.ToJson());
The pre-serializer function should return a valid JSON string. The output is re-serialized through System.Text.Json to ensure consistent formatting. Key order from the pre-serializer is preserved as-is.
To remove all registered pre-serializers (e.g., for test cleanup):
SnapshotSettings.ClearPreSerializers();
Caveats
Dynamic objects
You cannot call neither extension nor JestAssert with dynamic object. You need to cast it to object (or real type).
Credits
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- SystemTextJson.JsonDiffPatch (>= 2.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.