diff --git a/Src/FluentAssertions/Equivalency/EnumerableEquivalencyValidator.cs b/Src/FluentAssertions/Equivalency/EnumerableEquivalencyValidator.cs index 279dcd88cd..5af82aeccf 100644 --- a/Src/FluentAssertions/Equivalency/EnumerableEquivalencyValidator.cs +++ b/Src/FluentAssertions/Equivalency/EnumerableEquivalencyValidator.cs @@ -53,7 +53,7 @@ public void Execute(object[] subject, T[] expectation) private bool AssertIsNotNull(object expectation, object[] subject) { - return expectation != null || AssertionScope.Current + return AssertionScope.Current .ForCondition(!(expectation is null)) .FailWith("Expected {context:subject} to be , but found {0}.", new object[] { subject }); } diff --git a/Src/FluentAssertions/Equivalency/GenericDictionaryEquivalencyStep.cs b/Src/FluentAssertions/Equivalency/GenericDictionaryEquivalencyStep.cs index c08b704043..9744027415 100644 --- a/Src/FluentAssertions/Equivalency/GenericDictionaryEquivalencyStep.cs +++ b/Src/FluentAssertions/Equivalency/GenericDictionaryEquivalencyStep.cs @@ -13,6 +13,12 @@ namespace FluentAssertions.Equivalency /// public class GenericDictionaryEquivalencyStep : IEquivalencyStep { + private static readonly MethodInfo AssertSameLengthMethod = new Func, IDictionary, bool> + (AssertSameLength).GetMethodInfo().GetGenericMethodDefinition(); + + private static readonly MethodInfo AssertDictionaryEquivalenceMethod = new Action, IDictionary> + (AssertDictionaryEquivalence).GetMethodInfo().GetGenericMethodDefinition(); + public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config) { Type expectationType = config.GetExpectationType(context); @@ -51,14 +57,14 @@ private static bool PreconditionsAreMet(IEquivalencyValidationContext context, I private static bool AssertSubjectIsNotNull(object subject) { - return subject != null || AssertionScope.Current + return AssertionScope.Current .ForCondition(!(subject is null)) .FailWith("Expected {context:Subject} not to be {0}.", new object[] { null }); } private static bool AssertExpectationIsNotNull(object subject, object expectation) { - return expectation != null || AssertionScope.Current + return AssertionScope.Current .ForCondition(!(expectation is null)) .FailWith("Expected {context:Subject} to be {0}, but found {1}.", null, subject); } @@ -159,9 +165,6 @@ private static Type GetIDictionaryInterface(Type expectedType) return GetIDictionaryInterfaces(expectedType).Single(); } - private static readonly MethodInfo AssertSameLengthMethod = new Func, IDictionary, bool> - (AssertSameLength).GetMethodInfo().GetGenericMethodDefinition(); - private static bool AssertSameLength( IDictionary subject, IDictionary expectation) where TExpectedKey : TSubjectKey @@ -238,9 +241,6 @@ private static Type GetIDictionaryInterface(Type expectedType) AssertDictionaryEquivalenceMethod.MakeGenericMethod(typeArguments).Invoke(null, new[] { context, parent, config, context.Subject, context.Expectation }); } - private static readonly MethodInfo AssertDictionaryEquivalenceMethod = new Action, IDictionary> - (AssertDictionaryEquivalence).GetMethodInfo().GetGenericMethodDefinition(); - private static void AssertDictionaryEquivalence( EquivalencyValidationContext context, IEquivalencyValidator parent, diff --git a/Src/FluentAssertions/Equivalency/GenericEnumerableEquivalencyStep.cs b/Src/FluentAssertions/Equivalency/GenericEnumerableEquivalencyStep.cs index 5427d87906..adf5cf5482 100644 --- a/Src/FluentAssertions/Equivalency/GenericEnumerableEquivalencyStep.cs +++ b/Src/FluentAssertions/Equivalency/GenericEnumerableEquivalencyStep.cs @@ -10,6 +10,9 @@ namespace FluentAssertions.Equivalency { public class GenericEnumerableEquivalencyStep : IEquivalencyStep { + private static readonly MethodInfo HandleMethod = new Action> + (HandleImpl).GetMethodInfo().GetGenericMethodDefinition(); + /// /// Gets a value indicating whether this step can handle the verificationScope subject and/or expectation. /// @@ -37,14 +40,11 @@ public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAsserti var interfaceTypes = GetIEnumerableInterfaces(expectedType); - if (interfaceTypes.Length != 1) - { - AssertionScope.Current - .ForCondition(interfaceTypes.Length == 1) - .FailWith("{context:Expectation} implements {0}, so cannot determine which one " + - "to use for asserting the equivalency of the collection. ", - interfaceTypes.Select(type => "IEnumerable<" + type.GetGenericArguments().Single() + ">").ToList()); - } + AssertionScope.Current + .ForCondition(interfaceTypes.Length == 1) + .FailWith(() => new FailReason("{context:Expectation} implements {0}, so cannot determine which one " + + "to use for asserting the equivalency of the collection. ", + interfaceTypes.Select(type => "IEnumerable<" + type.GetGenericArguments().Single() + ">"))); if (AssertSubjectIsCollection(context.Expectation, context.Subject)) { @@ -71,15 +71,12 @@ public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAsserti return true; } - private static readonly MethodInfo HandleMethod = new Action> - (HandleImpl).GetMethodInfo().GetGenericMethodDefinition(); - private static void HandleImpl(EnumerableEquivalencyValidator validator, object[] subject, IEnumerable expectation) => validator.Execute(subject, expectation?.ToArray()); private static bool AssertSubjectIsCollection(object expectation, object subject) { - bool conditionMet = subject != null || AssertionScope.Current + bool conditionMet = AssertionScope.Current .ForCondition(!(subject is null)) .FailWith("Expected {context:subject} not to be {0}.", new object[] {null}); diff --git a/Src/FluentAssertions/Equivalency/ObjectReference.cs b/Src/FluentAssertions/Equivalency/ObjectReference.cs index 3fc779b8a5..d23ec6c754 100644 --- a/Src/FluentAssertions/Equivalency/ObjectReference.cs +++ b/Src/FluentAssertions/Equivalency/ObjectReference.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using FluentAssertions.Common; namespace FluentAssertions.Equivalency @@ -11,6 +12,7 @@ internal class ObjectReference private readonly object @object; private readonly string path; private readonly bool? isComplexType; + private string[] pathElements; public ObjectReference(object @object, string path, bool? isComplexType = null) { @@ -36,22 +38,14 @@ public override bool Equals(object obj) return ReferenceEquals(@object, other.@object) && IsParentOf(other); } - string[] pathElements; - - string[] GetPathElements() => pathElements + private string[] GetPathElements() => pathElements ?? (pathElements = path.ToLowerInvariant().Replace("][", "].[").Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries)); private bool IsParentOf(ObjectReference other) { - string[] path = GetPathElements(), otherPath = other.GetPathElements(); - - if (otherPath.Length <= path.Length) - return false; - - for (int i = 0; i < path.Length; i++) - if (path[i] != otherPath[i]) - return false; - return true; + string[] path = GetPathElements(); + string[] otherPath = other.GetPathElements(); + return (otherPath.Length > path.Length) && otherPath.Take(path.Length).SequenceEqual(path); } ///