Swevo.AutoAssert 2.4.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Swevo.AutoAssert --version 2.4.0
                    
NuGet\Install-Package Swevo.AutoAssert -Version 2.4.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Swevo.AutoAssert" Version="2.4.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Swevo.AutoAssert" Version="2.4.0" />
                    
Directory.Packages.props
<PackageReference Include="Swevo.AutoAssert" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Swevo.AutoAssert --version 2.4.0
                    
#r "nuget: Swevo.AutoAssert, 2.4.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Swevo.AutoAssert@2.4.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Swevo.AutoAssert&version=2.4.0
                    
Install as a Cake Addin
#tool nuget:?package=Swevo.AutoAssert&version=2.4.0
                    
Install as a Cake Tool

AutoAssert

NuGet NuGet Downloads CI License: MIT .NET 10 Ready

Free, MIT-licensed fluent assertions for .NET. No commercial license required — ever.

Why AutoAssert?

Starting with v8, FluentAssertions requires a paid commercial license for use in commercial projects (via its Xceed partnership). AutoAssert provides the same fluent Should() syntax you already know, fully free and open source under MIT, for teams who don't want licensing fees attached to their test suite.

using AutoAssert;

result.Should().Be(42);
name.Should().NotBeNullOrEmpty();
items.Should().HaveCount(3);
action.Should().Throw<InvalidOperationException>().WithMessage("boom");

Fluent chaining

Every assertion method returns an AndConstraint<T>, so you can chain multiple checks on the same subject with .And:

"hello world".Should()
    .NotBeNullOrEmpty()
    .And.StartWith("hello")
    .And.EndWith("world")
    .And.Contain("lo wo");

5.Should().BePositive().And.BeLessThan(10);

Breaking change note (v2.0.0): assertion methods used to return void; they now return AndConstraint<T>. Existing call sites keep working unchanged (the return value can simply be discarded) — only code that explicitly typed a variable/delegate as void around a call would need updating, which is extremely rare for fluent assertion call sites.

AssertionScope

Wrap multiple assertions in an AssertionScope to collect all failures and report them together in a single exception, instead of stopping at the first one:

using (new AssertionScope())
{
    result.Name.Should().Be("Ada");
    result.Age.Should().Be(30);
    result.Email.Should().NotBeNullOrEmpty();
} // throws one AssertionFailedException listing every failure, if any occurred

Install

dotnet add package Swevo.AutoAssert

Optionally add the companion Roslyn analyzers, which catch common fluent-assertion mistakes at compile time (e.g. a bare subject.Should(); that asserts nothing, or an unawaited ThrowAsync/NotThrowAsync):

dotnet add package Swevo.AutoAssert.Analyzers

See src/AutoAssert.Analyzers/README.md for the full diagnostic list.

Supported assertions

Type Examples
Objects Be, NotBe, BeNull, NotBeNull, BeSameAs, BeOfType<T>, BeAssignableTo<T>, Match, BeEquivalentTo
Strings Be, Contain, StartWith, EndWith, NotStartWith, NotEndWith, BeNullOrEmpty, HaveLength, MatchRegex, NotMatchRegex, BeEquivalentTo, ContainEquivalentOf, Match (wildcards), BeUpperCased, BeLowerCased
Booleans BeTrue, BeFalse
Numerics (int/long/short/byte/uint/ulong/ushort/sbyte/double/float/decimal) Be, BeGreaterThan, BeLessThan, BeInRange, BeApproximately, BePositive, BeNegative, BeOneOf, BeNaN/NotBeNaN (double/float)
Collections HaveCount, HaveCountGreaterThan, HaveCountLessThan, Contain, Contain(predicate), ContainInOrder, BeEquivalentTo, Equal, ContainSingle, OnlyHaveUniqueItems, AllSatisfy, SatisfyRespectively, BeInAscendingOrder, BeInDescendingOrder
Dictionaries ContainKey, NotContainKey, ContainValue, NotContainValue, ContainKeyAndValue, HaveCount, BeEmpty, NotBeEmpty
Exceptions Throw<T>, ThrowAsync<T>, NotThrow, NotThrow<T>, NotThrowAsync, WithMessage, WithMessageContaining, WithMessageMatching (wildcards), WithInnerException<T>, Where(predicate), WithParameterName
Value-returning functions Func<T>.Should().Throw<TException>()/.NotThrow(), Func<Task<T>>.Should().ThrowAsync<TException>()/.NotThrowAsync() (both return the resolved value)
Dates/times DateTime/DateTimeOffset: Be, NotBe, BeBefore, BeAfter, BeOnOrBefore, BeOnOrAfter, BeCloseTo, BeSameDateAs. TimeSpan: Be, BeGreaterThan, BeLessThan, BeCloseTo
Guid Be, NotBe, BeEmpty, NotBeEmpty
Nullable<T> HaveValue, NotHaveValue, Be, NotBe
Enums Be, NotBe, HaveFlag, NotHaveFlag
Execution time action.ExecutionTime().Should().BeLessThan/BeLessOrEqualTo/BeGreaterThan, action.Should().CompleteWithin(TimeSpan), func.Should().CompleteWithinAsync(TimeSpan)

Every assertion accepts an optional because reasoning clause, matching the syntax you're used to:

result.Should().Be(42, "the answer should always be 42");

BeEquivalentTo

BeEquivalentTo performs deep structural comparison of public readable properties and public fields. It works for plain objects, nested object graphs, and collections of objects, and reports a full diff of every mismatched member (not just the first one found).

using AutoAssert;

var actual = new OrderDto
{
    Id = 42,
    Customer = new CustomerDto { Name = "Ada" },
    Lines = [new OrderLineDto { Sku = "ABC", Quantity = 2 }]
};

var expected = new
{
    Id = 42,
    Customer = new { Name = "Ada" },
    Lines = new[] { new { Sku = "ABC", Quantity = 2 } }
};

actual.Should().BeEquivalentTo(expected);

Configure the comparison with an options callback:

actual.Should().BeEquivalentTo(expected, options => options
    .Excluding(x => x.Id)
    .Excluding("SomeFieldName")
    .WithStrictOrdering()); // require collections to match in the same order

Current scope:

  • compares public readable properties and public fields recursively, reporting every mismatched member (not only the first) at any depth
  • treats collections as order-independent by default; WithStrictOrdering() switches to positional (order-dependent) comparison
  • for order-independent collections, when no perfect item-to-item matching exists, every expected item's full diff is reported (via a greedy best-fit pairing), not just the first blocking mismatch
  • Excluding(...) skips named members or members selected via an expression, at the top level
  • uses value equality for primitives, strings, enums, dates, GUIDs, and other value types
  • ignores extra public members on the actual value when the expected value has fewer members
  • protects against infinite recursion on circular object graphs

Remaining limitation versus FluentAssertions: the greedy best-fit pairing used for reporting order-independent collection diffs isn't guaranteed globally optimal (unlike the exhaustive backtracking search used to detect whether a perfect match exists at all) — in rare cases with many near-duplicate items it may not report the minimal possible diff, though it always reports a diff for every expected item.

Global equivalency defaults

Configure BeEquivalentTo options once for the whole test suite (e.g. always excluding an audit-tracking Id/CreatedAt member), instead of repeating the same options at every call site:

// e.g. in a test assembly module initializer or a shared fixture's constructor
AssertionConfig.ConfigureEquivalency(options => options
    .Excluding("Id")
    .Excluding("CreatedAt"));

Every BeEquivalentTo(expected) call that doesn't specify its own options callback picks up these defaults automatically. A call that does provide options => ... still starts from the global defaults and layers its own configuration on top. AssertionConfig.ResetEquivalencyDefaults() restores the out-of-the-box (no exclusions, order-independent) behavior.

Note: this is process-wide mutable state, same trade-off FluentAssertions' own AssertionOptions has — avoid relying on it in test suites that run test classes in parallel with per-class differing configuration, since configuration set by one test can affect another running concurrently.

Colorized diff output

Enable ANSI color highlighting of expected/actual values in failure messages — expected values are rendered green, actual values red — for the most commonly hit assertions (BeEquivalentTo member mismatches, Object.Should().Be, String.Should().Be):

AssertionConfig.UseColorizedOutput = true;
  • Off by default, since many test runners (e.g. the Visual Studio Test Explorer output pane) render raw ANSI escape codes as garbage rather than interpreting them. It's most useful for CI logs and terminal-based test runners (dotnet test in a real console) that do interpret ANSI codes.
  • Like ConfigureEquivalency, this is process-wide mutable state — avoid toggling it from tests that run in parallel with others that assert on exact failure-message text.

Wildcard exception message matching

WithMessageMatching asserts an exception's message against a wildcard pattern (* matches any run of characters, ? matches a single character) — handy when a message contains a generated ID or other value you don't want to hardcode:

Action act = () => throw new InvalidOperationException("Order 12345 was not found");

act.Should().Throw<InvalidOperationException>()
    .WithMessageMatching("Order * was not found");

Snapshot testing

MatchSnapshot() serializes the subject to indented JSON and compares it against a baseline file stored in a __snapshots__ folder next to the calling test file — no separate snapshot library needed:

var result = BuildOrderSummary();

result.Should().MatchSnapshot();
  • First run: no baseline exists yet, so one is written (__snapshots__/{TestMethodName}.snapshot.json) and the assertion passes. Commit this file to source control as your golden file.
  • Subsequent runs: the current value is compared against the committed baseline; a mismatch throws an AssertionFailedException showing both the expected (baseline) and actual JSON.
  • Use MatchSnapshot("someName") to take multiple named snapshots within a single test method.
  • If a change is intentional, delete the corresponding __snapshots__/*.snapshot.json file and re-run the test to record a new baseline.
  • Pass scrub: to normalize non-deterministic values (generated GUIDs, "now"-based timestamps) before comparison, so they don't cause spurious snapshot failures:
result.Should().MatchSnapshot(
    scrub: SnapshotScrubbers.Combine(SnapshotScrubbers.Guids(), SnapshotScrubbers.IsoTimestamps()));

Custom assertions

Every assertion type is a public struct, so you can extend AutoAssert with your own domain-specific assertions exactly like the built-in FloatingPointAssertionExtensions does for NumericAssertions<T>:

public static class MyCustomAssertionExtensions
{
    public static AndConstraint<StringAssertions> BeAValidSku(this StringAssertions assertions, string because = "", params object[] becauseArgs)
    {
        // use AssertionHelpers.Fail(...) to report failures consistently (respects AssertionScope)
        return new AndConstraint<StringAssertions>(assertions);
    }
}

Companion packages

Package Description
Swevo.AutoAssert.Analyzers Dev-only Roslyn analyzers that catch discarded .Should() calls and unawaited async assertions at compile time.
Swevo.AutoAssert.Generator Source generator that emits a reflection-free BeEquivalentTo comparer for types marked [GenerateEquivalencyComparer] — faster and AOT-friendly.
Swevo.AutoAssert.AspNetCore Fluent HttpResponseMessage assertions (status code, headers, content type, string/JSON body) for WebApplicationFactory/HttpClient integration tests.
Swevo.AutoAssert.Json Fluent assertions on raw JSON strings (BeValidJson, HaveJsonProperty, BeEquivalentToJson) with full structural diffs.

Design goals

  • MIT licensed, forever. No commercial tier, no per-seat fees.
  • Zero reflection where possible — most assertions are plain equality/comparison checks; BeEquivalentTo uses public-member traversal.
  • AOT-safe — works with Native AOT test hosts.
  • Framework agnostic — throws a plain AssertionFailedException, recognized as a failure by xUnit, NUnit, and MSTest alike.
  • Familiar syntax — migrating from FluentAssertions should mostly be a find-and-replace of the using statement for the assertion types covered above.
Package Downloads Description
Swevo.AutoBus Downloads Free, MIT-licensed in-process message bus for
Swevo.AutoBus.RabbitMQ Downloads RabbitMQ transport for AutoBus
Swevo.AutoAuth Downloads A free, MIT-licensed fluent configuration wrapper around OpenIddict for building OAuth2/OIDC token servers in ASP
Swevo.AutoAudit Downloads Compile-time audit field generation for EF Core entities using Roslyn source generators
Swevo.AutoResult Downloads Compile-time Result<T> monad for
Swevo.AutoGuard Downloads Compile-time guard clauses for
Swevo.AutoImage Downloads A free, MIT-licensed fluent image processing wrapper around SkiaSharp for
Swevo.AutoFeatureFlag Downloads Compile-time feature flag stubs for
Swevo.AutoTestData Downloads Compile-time test data builders for

💼 Need .NET consulting?

I'm the author of AutoAssert and a suite of compile-time source generators (AutoWire, AutoMap.Generator) and 28+ Polly v8 resilience packages. I'm available for consulting on Polly v8 resilience, Azure cloud architecture, and clean .NET design.

→ solidqualitysolutions.com · LinkedIn

Also by the same author

🌐 Full suite overview: swevo.github.io

Package Description
FluentPdf Free, MIT-licensed fluent PDF generation — alternative to QuestPDF's commercial license.
AutoBus Free, MIT-licensed message bus — alternative to MassTransit's commercial license.
AutoArchitecture Free, MIT-licensed compile-time architecture rule enforcement — alternative to NDepend.
EFCore.BulkOperations Free, MIT-licensed bulk insert/update/delete for EF Core.
AutoWire Compile-time DI auto-registration — [Scoped]/[Singleton]/[Transient] generates IServiceCollection registration code.
AutoMap.Generator Compile-time object mapping — [Map(typeof(Dto))] generates ToDto() extension methods.
AutoValidate.Generator Compile-time FluentValidation wiring.
AutoResult.Generator Compile-time Result<T> monad.
AutoDispatch.Generator Compile-time CQRS dispatcher — free alternative to MediatR's commercial license.
PollyAnalyzers Free Roslyn analyzers for async/resilience anti-patterns — blocking calls, async void, fire-and-forget tasks, swallowed exceptions.
PollyAction Free retry/backoff GitHub Action — wrap any CI step with exponential-backoff retries.

License

MIT © Justin Bannister

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Swevo.AutoAssert:

Package Downloads
Swevo.AutoAssert.Json

Fluent assertions for raw JSON strings: validate JSON, assert dotted/indexed properties, and compare full JSON structures with clear diffs (object-key-order-insensitive).

Swevo.AutoAssert.AspNetCore

Fluent HttpResponseMessage assertions for ASP.NET Core integration tests. Assert status codes, headers, content type, string body, and JSON body equivalency for WebApplicationFactory/TestServer and HttpClient scenarios.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.4.1 158 10/1/2026
2.4.0 159 9/29/2026
1.1.1 137 8/7/2026
1.1.0 136 7/10/2026
1.0.1 127 7/7/2026
1.0.0 139 7/7/2026

2.4.0: Add ExceptionAssertions.WithMessageMatching for wildcard exception message assertions. Add AssertionConfig.UseColorizedOutput to render expected/actual values in ANSI green/red for BeEquivalentTo member-mismatch diffs and Object/String Be/NotBe failures (opt-in, off by default). 2.3.0: Add SnapshotScrubbers (Guids/IsoTimestamps/Pattern/Combine) and a MatchSnapshot(scrub:) parameter to normalize non-deterministic values before snapshot comparison. Add StringAssertions.Subject public accessor (used by the new Swevo.AutoAssert.Json companion package). New companion package: Swevo.AutoAssert.Json (BeValidJson, HaveJsonProperty, HaveJsonPropertyEqualTo, BeEquivalentToJson for raw JSON strings with full structural diffs). 2.2.0: Add companion packages: Swevo.AutoAssert.Generator (compile-time, reflection-free BeEquivalentTo comparers via [GenerateEquivalencyComparer]) and Swevo.AutoAssert.AspNetCore (fluent HttpResponseMessage assertions for WebApplicationFactory/HttpClient integration tests). Core: BeEquivalentTo now consults a GeneratedEquivalencyRegistry fast path before falling back to reflection when both sides are an exact, registered type. 2.1.0: Add AssertionConfig.ConfigureEquivalency for process-wide default BeEquivalentTo options, and MatchSnapshot() snapshot/golden-file testing (serializes the subject to JSON and compares against a baseline file next to the test, auto-recording it on first run). 2.0.0 (breaking): Every assertion method now returns AndConstraint<T> for fluent chaining (.And.Method()...) instead of void. Added AssertionScope for collecting multiple failures into one exception. BeEquivalentTo now supports Excluding(...)/WithStrictOrdering() options and reports a full diff of mismatched members instead of stopping at the first. Added DateTime/DateTimeOffset/TimeSpan/Guid/Nullable<T>/enum/IDictionary assertions, execution-time assertions (ExecutionTime()/CompleteWithin), unsigned numeric Should() overloads, and many new string/numeric/collection/exception assertion methods. 1.1.0: Add BeEquivalentTo deep structural equivalence for objects, nested graphs, and collections with circular-reference protection. 1.0.1: Add missing package icon. 1.0.0: Initial release. Object, string, numeric, boolean, collection, and exception assertions.