Summary
IgnoreLineEndingFormat (added in #4975) doesn't work for ContainsKey.
Minimal Reproducible Example
// tested with 4.4.0-alpha.0.17
[Test]
public void ContainKey()
{
Dictionary<string, int> values = new() { { "a\r", 1 } };
Assert.That(values, Does.ContainKey("a\n").IgnoreLineEndingFormat);
}
Explanation
The current implementation of DictionaryContainsKeyConstraint uses reflection:
|
private static MethodInfo? GetContainsKeyMethod(object keyedItemContainer) |
|
{ |
|
var instanceType = keyedItemContainer.GetType(); |
|
|
|
var method = FindContainsKeyMethod(instanceType) |
|
?? instanceType |
|
.GetInterfaces() |
|
.Concat(GetBaseTypes(instanceType)) |
|
.Select(FindContainsKeyMethod) |
|
.FirstOrDefault(m => m is not null); |
|
|
|
return method; |
|
} |
Unlike Enumerable.Contains, however, Dictionary<TKey,TValue>.ContainsKey(TKey) doesn't have an overload that takes in IEqualityComparer<TSource>. Therefore, DictionaryContainsKeyConstraint cannot use the IgnoreLineEndingFormatStringComparer
|
internal sealed class IgnoreLineEndingFormatStringComparer : IEqualityComparer<string> |
and therefore fails to treat
"a\r" and
"a\n" equally.
Potential Solution
Haven't looked too much into the code base, but the first thing I can think of is (in pseudocode):
- for
IDictionary<string, TValue>, do d.Keys.ToArray().Contains(key, IgnoreLineEndingFormatComparer<string>)
- for
IEnumerable<KeyValuePair<string, TValue>>, do d.Select(kvp => kvp.Key).Contains(key, IgnoreLineEndingFormatComparer<string>)
Summary
IgnoreLineEndingFormat(added in #4975) doesn't work forContainsKey.Minimal Reproducible Example
Explanation
The current implementation of
DictionaryContainsKeyConstraintuses reflection:nunit/src/NUnitFramework/framework/Constraints/DictionaryContainsKeyConstraint.cs
Lines 100 to 112 in d4a5c38
Unlike
Enumerable.Contains, however,Dictionary<TKey,TValue>.ContainsKey(TKey)doesn't have an overload that takes inIEqualityComparer<TSource>. Therefore,DictionaryContainsKeyConstraintcannot use theIgnoreLineEndingFormatStringComparernunit/src/NUnitFramework/framework/Constraints/Comparers/IgnoreLineEndingFormatStringComparer.cs
Line 10 in d4a5c38
"a\r"and"a\n"equally.Potential Solution
Haven't looked too much into the code base, but the first thing I can think of is (in pseudocode):
IDictionary<string, TValue>, dod.Keys.ToArray().Contains(key, IgnoreLineEndingFormatComparer<string>)IEnumerable<KeyValuePair<string, TValue>>, dod.Select(kvp => kvp.Key).Contains(key, IgnoreLineEndingFormatComparer<string>)