FluentAssertions
Assertion library for .NET — replaces Assert.AreEqual(expected, actual) with natural language assertion chains: result.Should().NotBeNull().And.HaveCount(3).And.ContainItemsAssignableTo<AgentDto>(). FluentAssertions features: object assertions (Be, NotBe, BeNull, BeEquivalentTo), collection assertions (HaveCount, Contain, BeInAscendingOrder), exception assertions (Throw<T>, ThrowAsync<T>), string assertions (Contain, Match, StartWith), numeric assertions (BePositive, BeInRange), date/time assertions (BeAfter, BeWithin), and custom assertion extension methods. Failure messages include full context explaining what was expected vs actual with diff. Works with xUnit, NUnit, and MSTest.
Score Breakdown
⚙ Agent Friendliness
🔒 Security
Test assertion library — no production security concerns. Ensure test assertion failures don't leak production agent credentials in CI/CD logs. Check FluentAssertions v7 licensing for commercial agent product teams.
⚡ Reliability
Best When
You're writing .NET agent service tests and want assertions that read like sentences and produce detailed failure messages — FluentAssertions makes test failures self-documenting.
Avoid When
Your assertions are simple one-liners, you're using non-.NET frameworks, or you prefer xUnit's built-in Assert class.
Use Cases
- • Readable agent test assertions — agentResult.Should().NotBeNull().And.BeEquivalentTo(expectedAgent, opts => opts.Excluding(x => x.CreatedAt)) asserts agent DTO matches expected ignoring timestamp field; readable and precise failure messages
- • Agent collection assertions — agents.Should().HaveCount(3).And.OnlyContain(a => a.IsActive).And.BeInAscendingOrder(a => a.Name) chains multiple agent collection assertions in one readable line
- • Agent exception testing — Func<Task> act = async () => await handler.Handle(invalidCmd, ct); await act.Should().ThrowAsync<ValidationException>().WithMessage('*Agent name*') asserts async handler throws correct validation exception
- • Agent object equivalence — createdAgent.Should().BeEquivalentTo(request, opts => opts.Excluding(x => x.Id).ExcludingMissingMembers()) asserts agent was created with request data using deep equality
- • Agent API response assertions — response.Should().HaveStatusCode(HttpStatusCode.Created).And.HaveHeader('Location').And.Satisfy<AgentDto>(dto => dto.Id.Should().NotBeEmpty()) chains HTTP response assertions
Not For
- • Production code assertions — FluentAssertions is test-only; use Guard.Against (Ardalis) or throw statements for production agent precondition validation
- • Simple single-line assertions — FluentAssertions shines for complex multi-property assertions; for simple null checks or equality, Assert.NotNull() is equally readable
- • Non-.NET test frameworks — FluentAssertions is .NET-only; for JavaScript agent tests use chai.js, for Python use assertpy or pytest's built-in assertions
Interface
Authentication
Test assertion library — no auth concepts.
Pricing
FluentAssertions 6.x is Apache 2.0. Version 7+ changed to dual license (Apache for non-commercial, commercial license for companies with revenue >$10M). Most teams can use free tier.
Agent Metadata
Known Gotchas
- ⚠ BeEquivalentTo uses structural equivalence not reference equality — agent1.Should().BeEquivalentTo(agent2) compares all public properties recursively; for agent objects with circular references, use ExcludingCyclicReferences() option; BeEquivalentTo on DateTime may fail due to precision differences — use Within(1.Seconds()) for agent timestamp comparisons
- ⚠ v7 license change requires evaluation for commercial use — FluentAssertions 7.x requires commercial license for companies with >$10M revenue; check license compliance before upgrading agent project from 6.x to 7.x; Shouldly is Apache 2.0 alternative if license is concern
- ⚠ Should() extension method requires using directive — must add 'using FluentAssertions;' to test file; Visual Studio suggests adding it but without it, Should() method is not found and test file won't compile for agent tests
- ⚠ ThrowAsync requires Func<Task> not Awaited result — Func<Task> act = async () => await handler.Handle(cmd); await act.Should().ThrowAsync<Exception>() is correct; don't await handler directly before assertion: (await handler.Handle(cmd)).Should().Throw() won't work for async agent exception testing
- ⚠ BeEquivalentTo default includes all properties including non-DTOs — when comparing agent entities vs DTOs, BeEquivalentTo may try to compare navigation properties causing recursion; use opts.Excluding(x => x.NavigationProperty) or ExcludingMissingMembers() for DTO comparison with incomplete property set
- ⚠ Collection assertion order matters — agents.Should().BeEquivalentTo(expected) does not consider order by default; use WithStrictOrdering() for ordered comparison; for agent test data that may return in different order from database, sort both sides or use BeEquivalentTo without strict ordering
Alternatives
Full Evaluation Report
Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for FluentAssertions.
Scores are editorial opinions as of 2026-03-06.