Skip to content

Conversation

@thomhurst
Copy link
Owner

@thomhurst thomhurst commented Jan 16, 2026

Summary

  • Adds Assert.That<TItem>(ICollection<TItem>?) overload with priority 3 (mutable)
  • Adds Assert.That<TItem>(IReadOnlyCollection<TItem>?) overload with priority 2 (read-only)
  • Both return CollectionAssertion<TItem> enabling collection-specific methods

Fixes #4446

Problem

When passing ICollection<T> or IReadOnlyCollection<T> to Assert.That(), the compiler selected the generic That<TValue>() fallback which returns ValueAssertion<T>, making collection-specific methods like IsEmpty() unavailable:

// This worked:
IEnumerable<int> numbers = [1, 2, 3];
await Assert.That(numbers).IsEmpty();

// This did not compile:
ICollection<int> numbers2 = [1, 2, 3];
await Assert.That(numbers2).IsEmpty();  // Error: no IsEmpty() method

Priority Design

Mutable collections get higher priority than read-only, matching the pattern used for other collection interfaces:

Interface Priority
TItem[] (Array) 5
IList<T> 4
ICollection<T> 3
ISet<T> 3
IDictionary<TKey, TValue> 3
HashSet<T> 3
IReadOnlyList<T> 3
IReadOnlyCollection<T> 2
IReadOnlyDictionary<TKey, TValue> 2
IReadOnlySet<T> 2
string 2
IEnumerable<T> 1
Memory<T> / ReadOnlyMemory<T> 1
IAsyncEnumerable<T> 1
Generic TValue fallback 0 (default)

Test plan

  • Added Issue4446Tests.cs with 13 tests covering ICollection<T> and IReadOnlyCollection<T> assertions
  • Added CollectionOverloadResolutionTests.cs with 47 tests covering all collection types to catch any ambiguity compilation errors
  • All tests pass
  • Build succeeds with no ambiguity errors

🤖 Generated with Claude Code

@thomhurst
Copy link
Owner Author

Summary

Adds Assert.That overloads for ICollection and IReadOnlyCollection to enable collection-specific assertions for these interface types.

Critical Issues

Missing PublicAPI snapshots

This PR adds public API methods to TUnit.Assertions.Extensions.Assert but does not include updated .verified.txt files. According to CLAUDE.md Rule 2: Changes to public APIs require running snapshot tests and committing .verified.txt files.

Required action:

  1. Run: dotnet test TUnit.PublicAPI
  2. Review the generated .received.txt files
  3. Rename them to .verified.txt
  4. Commit the .verified.txt files to this PR

Expected files to update:

  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt
  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt
  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt

Suggestions

Code review looks good:

  • Overload resolution priority of 2 is correct (between IEnumerable at 1 and more specific types at 3+)
  • Both overloads correctly return CollectionAssertion, enabling collection-specific methods
  • Test coverage is comprehensive (13 tests covering various scenarios)
  • Implementation follows existing patterns in the file

Verdict

REQUEST CHANGES - Missing required PublicAPI snapshot updates

@thomhurst
Copy link
Owner Author

Summary

Adds Assert.That overloads for ICollection and IReadOnlyCollection to enable collection-specific assertions.

Critical Issues

Still missing PublicAPI snapshots

The previous review comment identified this issue, but it remains unresolved. This PR adds public API methods to TUnit.Assertions but does not include updated .verified.txt files.

Per CLAUDE.md Rule 2: "Changes to source generator output or public APIs require running snapshot tests. Commit .verified.txt files. NEVER commit .received.txt."

Required action:

cd TUnit.PublicAPI
dotnet test
# Review the .received.txt files that are generated
# If they look correct, rename them to .verified.txt (see CLAUDE.md for commands)
git add *.verified.txt
git commit -m "chore: update PublicAPI snapshots"

Expected files to update:

  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet8_0.verified.txt
  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet9_0.verified.txt
  • TUnit.PublicAPI/Tests.Assertions_Library_Has_No_API_Changes.DotNet10_0.verified.txt

Previous Review Status

The PublicAPI issue was identified in the previous review but not yet addressed.

Code Quality ✅

The implementation is solid:

  • ✅ Priority values are correct (ICollection=3, IReadOnlyCollection=2) and consistent with existing patterns
  • ✅ Both return CollectionAssertion, correctly enabling collection methods
  • ✅ XML docs are clear and include examples
  • ✅ Test coverage is comprehensive (13 tests)
  • ✅ Follows existing code patterns in Assert.cs:154-187
  • ✅ No performance concerns
  • ✅ No AOT compatibility issues
  • ✅ No VSTest usage
  • ✅ Dual-mode rule doesn't apply (assertion library change)

Verdict

⚠️ REQUEST CHANGES - Missing required PublicAPI snapshot updates (mandatory per TUnit rules)

…tion<T>

Fixes #4446

When passing ICollection<T> or IReadOnlyCollection<T> to Assert.That(),
the compiler would select the generic That<TValue>() fallback which
returns ValueAssertion<T>, making collection-specific methods like
IsEmpty() unavailable.

Added two new overloads:
- Assert.That<TItem>(ICollection<TItem>?) with priority 3 (mutable)
- Assert.That<TItem>(IReadOnlyCollection<TItem>?) with priority 2 (read-only)

Mutable collections get higher priority than read-only, matching the
pattern used for other collection interfaces (IList vs IReadOnlyList,
IDictionary vs IReadOnlyDictionary, ISet vs IReadOnlySet).

Also added CollectionOverloadResolutionTests.cs to verify all collection
types compile without ambiguity and resolve to the correct assertion type.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@thomhurst
Copy link
Owner Author

Summary

Adds Assert.That overloads for ICollection (priority 3) and IReadOnlyCollection (priority 2) to enable collection-specific assertion methods like IsEmpty() and Contains().

Critical Issues

None found ✅

Suggestions

1. Consider snapshot testing impact

While these changes add new public API overloads to Assert.That(), I don't see any .verified.txt updates in the diff. According to CLAUDE.md rule #2 ("Changes to source generator output or public APIs require running snapshot tests"), you should verify if TUnit.PublicAPI snapshots need updating. If the public API analyzer is configured, running the snapshot tests should detect this.

To verify:

# Run snapshot tests to see if API snapshots need updating
dotnet test TUnit.Assertions.Tests --filter "FullyQualifiedName~PublicAPI" 

2. Excellent test coverage

The PR includes comprehensive test coverage with:

This demonstrates thoroughness and prevents regression.

3. Priority alignment looks correct

The priority scheme matches existing patterns:

  • Mutable collections (ICollection) → priority 3 (same as ISet, IDictionary<K,V>, HashSet)
  • Read-only collections (IReadOnlyCollection) → priority 2 (same as IReadOnlySet, IReadOnlyDictionary<K,V>, string)

This ensures IList (priority 4) takes precedence over ICollection, which is correct since IList is more specific.

Verdict

APPROVE (pending snapshot test verification)

The implementation follows TUnit patterns correctly, includes excellent test coverage, and solves the reported issue. The only potential concern is whether public API snapshots need updating - please verify this doesn't fail CI.

🤖 Generated with Claude Code

@thomhurst
Copy link
Owner Author

Summary

Adds Assert.That() overloads for ICollection and IReadOnlyCollection to enable collection-specific assertion methods like IsEmpty(), Contains(), etc.

Critical Issues

None found ✅

Suggestions

None - the implementation is solid:

  • Priorities are correctly set (ICollection=3, IReadOnlyCollection=2) matching the existing pattern
  • Both overloads return CollectionAssertion, providing access to all collection methods
  • Comprehensive test coverage with 13 issue-specific tests and 47 overload resolution tests
  • Public API snapshots properly updated (.verified.txt files committed)
  • Follows existing patterns (null-forgiving operator usage matches IEnumerable overload at line 71)
  • XML documentation is clear and includes usage examples

The CollectionOverloadResolutionTests.cs is particularly valuable - it will catch any future ambiguity regressions across all collection types.

Verdict

APPROVE - No critical issues

Excellent work addressing issue #4446. The fix is minimal, well-tested, and follows TUnit's established conventions.

This was referenced Jan 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Collection assertions don't work when type given to Assert.That is ICollection/ICollection<T>

2 participants