Fluent Assertions 8.7 is live

Version 8.7.0 makes API and object graph testing less brittle. You can now assert directly on JsonNode and JsonArray, fine-tune BeEquivalentTo with strict typing and member mapping, and use WithoutMessage to block unwanted exception text. Cleaner intent, fewer diffs, more trustworthy tests.

JSON-native asserts and sharper object graph comparisons

Fluent Assertions 8.7.0 is here, and it’s a meaningful step forward for teams testing JSON APIs and deep object graphs. This release brings first-class System.Text.Json support, upgrades to BeEquivalentTo precision, and a new way to validate exception messages. The net effect: fewer brittle diffs, more resilient test suites, and clearer intent in your specs.

Why it matters

  • JSON-native assertions – Directly assert structure, types, and values on JsonNode and JsonArray.
  • Sharper object graph equivalence – Fine-tune strict typing, member selection, and mapping for DTO vs. domain comparisons.
  • Cleaner exception specs – Use WithoutMessage to guarantee an exception message doesn’t match unwanted patterns.

JSON support

JSON payloads are now first-class citizens in your tests.

var node = JsonNode.Parse("{ \"name\": \"Product\", \"price\": 99.99 }");

node.Should().BeEquivalentTo(new { name = "Product", price = 99.99 });
node.Should().HaveProperty("name").Which.ToString().Should().Be("Product");
node.Should().NotHaveProperty("code");

JsonArray array = JsonNode.Parse("[1, 2, 3]")!.AsArray();
array.Should().NotBeEmpty();

Helpers like BeString, BeNumeric, BeBool, BeUtcDate, and BeAnArray make intent obvious at a glance. If casing differs, use IgnoringJsonPropertyCasing().

Object graph equivalence upgrades

BeEquivalentTo gets more precise, giving you surgical control over equivalence checks.

  • Strict typing controls
    • WithStrictTyping → enforce across the whole graph
    • WithStrictTypingFor → target specific paths
    • WithoutStrictTyping → override globally
  • Runtime vs. declared types
    • PreferringRuntimeMemberTypes() or PreferringDeclaredMemberTypes()
  • Member selection & mapping
    • Exclude noisy properties
    • Align mismatched names with WithMapping
  • Enums by name
    • ComparingEnumsByName() avoids numeric mismatches
  • Collections
    • AllBeEquivalentTo makes asserting homogeneous sets trivial

Exception assertions

A new option: WithoutMessage. This ensures an exception’s message does not contain a given wildcard pattern—handy for privacy requirements or sanitizing user-facing error messages.

Practical test design tips

  • Start strict where regressions matter most; keep the rest flexible.
  • Use mapping to stabilize DTO/domain differences without rewriting models.
  • Prefer runtime member types when dealing with proxies or dynamic types.
  • Use JSON-native asserts for API tests; keep BeEquivalentTo for structural comparisons.

Release rollup (8.7 → 8.1)

Recent highlights worth noting:

  • 8.6.0 – Value.ThatMatches and ThatSatisfies for inline assertions.
  • 8.5.0 – WithStrictTyping and WithStrictTypingFor.
  • 8.4.0 – ExcludingMembersNamed and new exception helpers.
  • 8.3.0 – Better date/time and exception message rendering.
  • 8.1.x – Fixes for dictionary formatting, NRT annotations, async task handling.

Full release notes →

Get started

  • Upgrade to 8.7.0 in your test project.
  • Review BeEquivalentTo usages — add strict typing where intent matters.
  • Switch to JSON-native asserts for clearer, more resilient API tests.