Skip to content

FluentAssertions

TestingC#

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 FluentAssertions

Getting started

The smallest useful thing you can do with it, and what each part means.

Readable assertions
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");
A failing collection assertion lists which items were present and which were expected, rather than reporting that two collections were unequal.

Advanced usage

Where the library earns its place over a simpler alternative.

Structural comparison
// 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".
BeEquivalentTo is the reason to adopt the library. Comparing a deep object graph by hand means a dozen assertions; this is one line and a better failure message.

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.