Exemplo n.º 1
0
        /// <summary>
        /// Assert that the given objects are equal, by checking each public property.
        /// </summary>
        /// <param name="expected">The expected value</param>
        /// <param name="actual">The actual value</param>
        /// <param name="deepCompare">Optionally perform a deep compare up to <see cref="DeepCompareMaximumDepth"/> levels deep. Default false.</param>
        /// <param name="propertyFilter">Optional filter to whitelist which properties to compare. If a given type contains no filter, defaults to all public properties of the type.</param>
        public static void AreEqual <T>(T expected, T actual, bool deepCompare = false, PropertyFilter propertyFilter = null)
        {
            if (propertyFilter == null)
            {
                propertyFilter = new PropertyFilter();
            }

            AssertPropertiesEqual(typeof(T), expected, actual, null, null, 0, deepCompare ? DeepCompareMaximumDepth : 1, propertyFilter);
        }
Exemplo n.º 2
0
        private static void AssertPropertiesEqual(Type type, object expected, object actual, string propertyPath, int?propertyIndex, int depth, int maxDepth, PropertyFilter propertyFilter)
        {
            if (depth >= maxDepth || IsValueType(type) || Equals(expected, null) || Equals(actual, null))
            {
                var propertyDescriptor = GetPropertyDescriptor(propertyPath, propertyIndex);
                Assert.AreEqual(expected, actual, propertyDescriptor);
                return;
            }

            // If the objects refer to the same instance in memory, then of course they are equal!
            if (ReferenceEquals(expected, actual))
            {
                return;
            }

            depth++;

            var expectedEnumerable = expected as IEnumerable;
            var actualEnumerable   = actual as IEnumerable;

            var enumerableInterface = type
                                      .GetInterfaces()
                                      .SingleOrDefault(i =>
                                                       i.IsGenericType &&
                                                       i.GetGenericTypeDefinition() == typeof(IEnumerable <>) &&
                                                       i.GenericTypeArguments.Length == 1);

            if (expectedEnumerable != null && actualEnumerable != null && enumerableInterface != null)
            {
                var enumerableType = enumerableInterface.GetGenericArguments().Single();
                var expectedArray  = expectedEnumerable.Cast <object>().ToArray();
                var actualArray    = actualEnumerable.Cast <object>().ToArray();

                if (expectedArray.Length != actualArray.Length)
                {
                    var propertyDescriptor = GetPropertyDescriptor(propertyPath, propertyIndex);
                    Assert.Fail($"{propertyDescriptor}{Environment.NewLine}  Expected length: {expectedArray.Length}{Environment.NewLine}  But was length:  {actualArray.Length}{Environment.NewLine}");
                }

                for (int i = 0; i < expectedArray.Length; i++)
                {
                    var expectedArrValue = expectedArray[i];
                    var actualArrValue   = actualArray[i];
                    var newPropertyPath  = GetNewPropertyPath(propertyPath, propertyIndex, null);

                    AssertPropertiesEqual(enumerableType, expectedArrValue, actualArrValue, newPropertyPath, i, depth, maxDepth, propertyFilter);
                }

                return;
            }

            foreach (var property in propertyFilter.GetFilteredOrAllProperties(type))
            {
                var expectedValue   = property.GetValue(expected, null);
                var actualValue     = property.GetValue(actual, null);
                var newPropertyPath = GetNewPropertyPath(propertyPath, propertyIndex, property.Name);

                // Skip self-referential recursive properties, which refer to the object itself (ie: GeoAPI Coordinate)
                if (property.PropertyType == type && ReferenceEquals(expected, expectedValue) && ReferenceEquals(actual, actualValue))
                {
                    continue;
                }

                AssertPropertiesEqual(property.PropertyType, expectedValue, actualValue, newPropertyPath, null, depth, maxDepth, propertyFilter);
            }
        }