What it is
FluentAssertions provides readable, chainable assertions for .NET with failure messages that explain precisely what differed.
Every assertion reads as a sentence. Object graph comparison, collection assertions and exception assertions all produce descriptive failures.
Installation
dotnet add package FluentAssertionsGetting started
The smallest useful thing you can do with it, and what each part means.
csharp
result.Should().NotBeNull();
result.Title.Should().Be("Dune").And.NotBeNullOrWhiteSpace();
result.Year.Should().BeInRange(1900, 2000);
books.Should().HaveCount(3)
.And.OnlyHaveUniqueItems()
.And.BeInDescendingOrder(b => b.Year)
.And.Contain(b => b.Title == "Dune");
var act = () => service.Delete(null!);
act.Should().Throw<ArgumentNullException>()
.WithParameterName("book");Advanced usage
Where the library earns its place over a simpler alternative.
csharp
// Compares by value across the whole graph, not by reference.
actual.Should().BeEquivalentTo(expected, options => options
.Excluding(b => b.Id) // generated, ignore it
.Excluding(b => b.CreatedAt)
.Using<DateTime>(ctx => ctx.Subject.Should()
.BeCloseTo(ctx.Expectation, TimeSpan.FromSeconds(1)))
.WhenTypeIs<DateTime>());
// On failure it names the exact path:
// Expected member Author.Country to be "US", but found "UK".Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- BeEquivalentTo fails on unrelated properties
- It compares everything by default. Exclude generated members or use a projection.
- Build warning about licensing
- FluentAssertions 8 changed licence. Pin to 7.x, or evaluate Shouldly or AwesomeAssertions.
Best practices
- Use BeEquivalentTo for object graphs and exclude generated fields such as ids and timestamps.
- Use BeCloseTo for times; exact equality on DateTime is flaky.
- Add a because reason on non-obvious assertions — it appears in the failure output.
- Check the licence: version 8 requires a paid licence for commercial use, so pin version 7 if that matters.
Background
Why it exists, and what it was reacting to.
Its value is diagnostic: Assert.Equal reports two values, while FluentAssertions names the property that differed inside a nested object graph — turning a puzzling failure into an obvious one.
