From 80fb845251c67b131b0dcdd396ee20f6673f2134 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Mon, 17 Aug 2026 21:18:10 +1000 Subject: [PATCH] Keep empty collections ignored alongside instance predicates TryGetScrubOrIgnoreByInstance returned as soon as it found predicates registered for the value's type and none of them matched, skipping the empty collection check below it. So an empty List started rendering as [] merely because some unrelated IgnoreInstance or ScrubInstance predicate had been registered for that type. No predicate matching is not a decision to keep the value, so the empty collection check now runs either way. The test lives in its own file rather than being appended to SerializationTests, so this does not collide with the other pending fixes that append there. --- ...ateKeepsEmptyCollectionsIgnored.verified.txt | 5 +++++ .../Serialization/IgnoreInstanceTests.cs | 17 +++++++++++++++++ .../SerializationSettings_ShouldIgnore.cs | 5 ++--- src/todo.md | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 src/Verify.Tests/Serialization/IgnoreInstanceTests.NonMatchingPredicateKeepsEmptyCollectionsIgnored.verified.txt create mode 100644 src/Verify.Tests/Serialization/IgnoreInstanceTests.cs diff --git a/src/Verify.Tests/Serialization/IgnoreInstanceTests.NonMatchingPredicateKeepsEmptyCollectionsIgnored.verified.txt b/src/Verify.Tests/Serialization/IgnoreInstanceTests.NonMatchingPredicateKeepsEmptyCollectionsIgnored.verified.txt new file mode 100644 index 0000000000..dbdf9b6b37 --- /dev/null +++ b/src/Verify.Tests/Serialization/IgnoreInstanceTests.NonMatchingPredicateKeepsEmptyCollectionsIgnored.verified.txt @@ -0,0 +1,5 @@ +{ + NotEmpty: [ + TheValue + ] +} \ No newline at end of file diff --git a/src/Verify.Tests/Serialization/IgnoreInstanceTests.cs b/src/Verify.Tests/Serialization/IgnoreInstanceTests.cs new file mode 100644 index 0000000000..939da02359 --- /dev/null +++ b/src/Verify.Tests/Serialization/IgnoreInstanceTests.cs @@ -0,0 +1,17 @@ +public class IgnoreInstanceTests +{ + [Fact] + public Task NonMatchingPredicateKeepsEmptyCollectionsIgnored() => + Verify( + new + { + Empty = new List(), + NotEmpty = new List + { + "TheValue" + } + }) + // a predicate that never matches is not a decision to keep the value, + // so Empty is still ignored as an empty collection + .IgnoreInstance>(_ => false); +} diff --git a/src/Verify/Serialization/SerializationSettings_ShouldIgnore.cs b/src/Verify/Serialization/SerializationSettings_ShouldIgnore.cs index e95b6be33f..f0ea74045d 100644 --- a/src/Verify/Serialization/SerializationSettings_ShouldIgnore.cs +++ b/src/Verify/Serialization/SerializationSettings_ShouldIgnore.cs @@ -23,6 +23,8 @@ internal bool TryGetScrubOrIgnore(Type declaringType, Type memberType, string na internal bool TryGetScrubOrIgnoreByInstance(object value, [NotNullWhen(true)] out ScrubOrIgnore? scrubOrIgnore) { var memberType = value.GetType(); + // no predicate matching is not a decision to keep the value, so + // the empty collection check still applies if (GetShouldIgnoreInstance(memberType, out var funcs)) { foreach (var func in funcs) @@ -34,9 +36,6 @@ internal bool TryGetScrubOrIgnoreByInstance(object value, [NotNullWhen(true)] ou return true; } } - - scrubOrIgnore = null; - return false; } if (ignoreEmptyCollections && diff --git a/src/todo.md b/src/todo.md index 03784f69b0..5ce2b47c5f 100644 --- a/src/todo.md +++ b/src/todo.md @@ -44,7 +44,7 @@ All six resolved 2026-08-16 (five fixed here; the inline item resolved as by-des - [ ] **`MemberConverter` has no exact-type precedence.** `Verify/Serialization/VerifierSettings_MemberConverter.cs:13-25` — first registered entry with `IsAssignableFrom` wins, so a base-interface converter registered earlier permanently shadows a more specific one. Contrast `TryGetScrubOrIgnoreByMemberOfType`, which checks the exact declaring type first. -- [ ] **Registering an `IgnoreInstance` predicate disables empty-collection ignoring for that type.** +- [x] **Registering an `IgnoreInstance` predicate disables empty-collection ignoring for that type.** `Verify/Serialization/SerializationSettings_ShouldIgnore.cs:26-40` — when predicates exist but none match, the early `return false` skips the `ignoreEmptyCollections` check at 42-47. An empty `List` starts appearing as `[]` merely because an unrelated predicate was registered. - [ ] **Combinations name cache collapses distinct keys.**