Skip to content

Add public ValueTypeAssertions<TSubject, TAssertions> base class - #3308

Open
dennisdoomen wants to merge 1 commit into
mainfrom
dennisdoomen-value-type-assertions-base-class
Open

Add public ValueTypeAssertions<TSubject, TAssertions> base class#3308
dennisdoomen wants to merge 1 commit into
mainfrom
dennisdoomen-value-type-assertions-base-class

Conversation

@dennisdoomen

Copy link
Copy Markdown
Member

Closes #3292

What

Adds a public ValueTypeAssertions<TSubject, TAssertions> base class in FluentAssertions.Primitives, giving third-party assertion authors a ready-made base for value types (structs), mirroring what ReferenceTypeAssertions<TSubject, TAssertions> already offers for reference types.

API

public abstract class ValueTypeAssertions<TSubject, TAssertions>
    where TSubject : struct
    where TAssertions : ValueTypeAssertions<TSubject, TAssertions>
{
    protected ValueTypeAssertions(TSubject? subject, AssertionChain assertionChain);

    public TSubject? Subject { get; }
    public AssertionChain CurrentAssertionChain { get; }
    protected abstract string Identifier { get; }

    public AndConstraint<TAssertions> Be(TSubject expected, string because = "", params object[] becauseArgs);
    public AndConstraint<TAssertions> NotBe(TSubject unexpected, string because = "", params object[] becauseArgs);
    public AndConstraint<TAssertions> BeNull(string because = "", params object[] becauseArgs);
    public AndConstraint<TAssertions> NotBeNull(string because = "", params object[] becauseArgs);
    public AndConstraint<TAssertions> Match(Expression<Func<TSubject, bool>> predicate, string because = "", params object[] becauseArgs);
}

The constructor and CurrentAssertionChain/WithDefaultIdentifier usage follow the same conventions already used by ReferenceTypeAssertions, BooleanAssertions, and the other primitive assertion classes in this codebase, rather than the constructor shape shown in the issue's proposal (which predates the AssertionChain pattern).

Changes

  • Src/FluentAssertions/Primitives/ValueTypeAssertions.cs — new base class.
  • Tests/FluentAssertions.Specs/Primitives/ValueTypeAssertionsSpecs.cs — specs covering Be, NotBe, BeNull, NotBeNull, Match, and the Equals guard, using a Coordinates struct/CoordinatesAssertions test fixture.
  • Tests/Approval.Tests/ApprovedApi/**/*.verified.txt — updated via AcceptApiChanges.ps1 for the new public API.
  • docs/_pages/extensibility.md — mentions the new base class alongside ReferenceTypeAssertions.
  • docs/_pages/releases.md — release note entry.

Testing

  • dotnet test Tests/FluentAssertions.Specs/FluentAssertions.Specs.csproj --filter "FullyQualifiedName~Primitives" — all pass (net47/net6.0/net8.0).
  • dotnet test Tests/Approval.Tests/Approval.Tests.csproj — all pass after accepting the API change.

Comment thread Tests/FluentAssertions.Specs/Primitives/ValueTypeAssertionsSpecs.cs Fixed
@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown

Test Results

0 files   -     37  0 suites   - 37   0s ⏱️ - 2m 25s
0 tests  -  6 458  0 ✅  -  6 457  0 💤  - 1  0 ❌ ±0 
0 runs   - 40 094  0 ✅  - 40 088  0 💤  - 6  0 ❌ ±0 

Results for commit 6fd822e. ± Comparison against base commit f298d15.

♻️ This comment has been updated with latest results.

@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 31400945909

Warning

No base build found for commit ec238bd on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 97.184%

Details

  • Patch coverage: 46 of 46 lines across 1 file are fully covered (100%).

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 13511
Covered Lines: 13285
Line Coverage: 98.33%
Relevant Branches: 4388
Covered Branches: 4110
Branch Coverage: 93.66%
Branches in Coverage %: Yes
Coverage Strength: 67635.09 hits per line

💛 - Coveralls

@dennisdoomen
dennisdoomen marked this pull request as draft August 10, 2026 16:59
@dennisdoomen dennisdoomen added this to the 8.11 milestone Aug 15, 2026
@dennisdoomen
dennisdoomen force-pushed the dennisdoomen-value-type-assertions-base-class branch from f1a7c19 to 673be2d Compare August 15, 2026 10:10
@dennisdoomen
dennisdoomen force-pushed the dennisdoomen-value-type-assertions-base-class branch from 673be2d to e9db98c Compare August 15, 2026 12:28
@dennisdoomen
dennisdoomen force-pushed the dennisdoomen-value-type-assertions-base-class branch from e9db98c to 6af3dd1 Compare August 15, 2026 12:29
Adds a base class for building custom assertions on value types (structs),
mirroring ReferenceTypeAssertions for reference types. It provides Be,
NotBe, BeNull, NotBeNull and Match, driven by an overridable Identifier
property for consistent failure messages.

Closes #3292

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@dennisdoomen
dennisdoomen force-pushed the dennisdoomen-value-type-assertions-base-class branch from 6af3dd1 to 6fd822e Compare August 15, 2026 12:30
@dennisdoomen
dennisdoomen marked this pull request as ready for review August 15, 2026 12:30
@dennisdoomen
dennisdoomen requested a review from jnyrup August 15, 2026 12:31
@github-actions

Copy link
Copy Markdown

Qodana for .NET

It seems all right 👌

No new problems were found according to the checks applied

💡 Qodana analysis was run in the pull request mode: only the changed files were checked
☁️ View the detailed Qodana report

Contact Qodana team

Contact us at qodana-support@jetbrains.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Public ValueTypeAssertions<TSubject, TAssertion>; base class for custom value-type assertions

2 participants