public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            bool expectationIsNotNull = AssertionScope.Current
                .ForCondition(!ReferenceEquals(context.Expectation, null))
                .FailWith(
                    "Expected {context:subject} to be <null>, but found {0}.",
                    context.Subject);

            bool subjectIsNotNull =
                AssertionScope.Current.ForCondition(
                    !ReferenceEquals(context.Subject, null))
                    .FailWith(
                        "Expected {context:object} to be {0}{reason}, but found {1}.",
                        context.Expectation,
                        context.Subject);

            IEnumerable<SelectedMemberInfo> selectedMembers = GetSelectedMembers(context, config).ToArray();
            if (context.IsRoot && !selectedMembers.Any())
            {
                throw new InvalidOperationException(
                    "No members were found for comparison. " +
                    "Please specify some members to include in the comparison or choose a more meaningful assertion.");
            }

            if (expectationIsNotNull && subjectIsNotNull)
            {
                foreach (var selectedMemberInfo in selectedMembers)
                {
                    AssertMemberEquality(context, parent, selectedMemberInfo, config);
                }
            }
            return true;
        }
 public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
     IEquivalencyAssertionOptions config)
 {
     return config.UserEquivalencySteps
         .Where(s => s.CanHandle(context, config))
         .Any(step => step.Handle(context, parent, config));
 }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type subjectType = config.GetSubjectType(context);

            return ((subjectType != null) && subjectType.IsEnum()) ||
                   ((context.Expectation != null) && context.Expectation.GetType().IsEnum());
        }
        public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config)
        {
            IEnumerable<PropertyInfo> propertyInfos =
                selectedMembers.OfType<PropertySelectedMemberInfo>().Select(info => info.PropertyInfo);

            return obsoleteSelectionRule.SelectProperties(propertyInfos, context).Select(SelectedMemberInfo.Create);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent,
            IEquivalencyAssertionOptions config)
        {
            context.Subject.Should().Be(context.Expectation, context.Reason, context.ReasonArgs);

            return true;
        }
        public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath, IEquivalencyAssertionOptions config)
        {
            SelectedMemberInfo compareeSelectedMemberInfoInfo = null;

            if (config.IncludeProperties)
            {
                compareeSelectedMemberInfoInfo = SelectedMemberInfo.Create(expectation.GetType()
                    .FindProperty(subjectMember.Name, subjectMember.MemberType));
            }

            if ((compareeSelectedMemberInfoInfo == null) && config.IncludeFields)
            {
                compareeSelectedMemberInfoInfo = SelectedMemberInfo.Create(expectation.GetType()
                    .FindField(subjectMember.Name, subjectMember.MemberType));
            }

            if ((compareeSelectedMemberInfoInfo == null) && ExpectationImplementsMemberExplicitly(expectation, subjectMember))
            {
                compareeSelectedMemberInfoInfo = subjectMember;
            }
            
            if (compareeSelectedMemberInfoInfo == null)
            {
                string path = (memberPath.Length > 0) ? memberPath + "." : "member ";

                Execute.Assertion.FailWith(
                    "Subject has " + path + subjectMember.Name + " that the other object does not have.");
            }

            return compareeSelectedMemberInfoInfo;
        }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(EquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type type = context.RuntimeType;

            return (type != null) &&
                   (type != typeof (object)) &&
                   (type.Namespace == typeof (int).Namespace);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            if (context.PropertyInfo != null)
            {
                return config.AssertionRules.Any(rule => rule.AssertEquality(context));
            }

            return false;
        }
        public bool Handle(
            IEquivalencyValidationContext context,
            IEquivalencyValidator parent,
            IEquivalencyAssertionOptions config)
        {
            var equivalencyValidationContext = CreateAdjustedCopy(context);

            return eqivalencyStep.Handle(equivalencyValidationContext, parent, config);
        }
            public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator
                               parent, IEquivalencyAssertionOptions config)
            {
                var subject     = (TSubject)context.Subject;
                var expectation = (TExpectation)context.Expectation;

                Test(subject, expectation, context.Because, context.BecauseArgs);

                return(true);
            }
 internal static void ConfigureOrderingRules <TActual>(
     EquivalencyAssertionOptions <TActual> actualOptions,
     IEquivalencyAssertionOptions subConfigOptions)
 {
     foreach (IOrderingRule orderingRule in subConfigOptions.OrderingRules)
     {
         ((IEquivalencyAssertionOptions)actualOptions).OrderingRules.Add(
             new CollectionMemberOrderingRuleDecorator(orderingRule));
     }
 }
 internal static void ConfigureAssertionRules <TActual>(
     EquivalencyAssertionOptions <TActual> actualOptions,
     IEquivalencyAssertionOptions subConfigOptions)
 {
     //Reverse order because Using prepends
     foreach (var assertionRule in subConfigOptions.AssertionRules.Reverse())
     {
         actualOptions.Using(new CollectionMemberAssertionRuleDecorator(assertionRule));
     }
 }
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
                           IEquivalencyAssertionOptions config)
        {
            if (PreconditionsAreMet(context, config))
            {
                AssertDictionaryEquivalence(context, parent, config);
            }

            return(true);
        }
Exemple #14
0
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type type = config.GetSubjectType(context);

            return
                ((type != null) &&
                 (type != typeof(object)) &&
                 config.IsValueType(type) &&
                 !type.IsArray);
        }
 private static void ConfigureAssertionRules <TActual>(
     EquivalencyAssertionOptions <TActual> actualOptions,
     IEquivalencyAssertionOptions subConfigOptions)
 {
     // Reverse order because Using prepends
     foreach (var equivalencyStep in subConfigOptions.UserEquivalencySteps.Reverse())
     {
         actualOptions.Using(new CollectionMemberAssertionRuleDecorator(equivalencyStep));
     }
 }
        public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config)
        {
            string path = context.SelectedMemberPath;
            if (!ContainsIndexingQualifiers(pathToExclude))
            {
                path = RemoveInitialIndexQualifier(path);
            }

            return selectedMembers.Where(memberInfo => (path.Combine(memberInfo.Name) != pathToExclude)).ToArray();
        }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type type = config.GetSubjectType(context);

            return 
                (type != null) && 
                (type != typeof (object)) && 
                config.IsValueType(type) && 
                !type.IsArray;
        }
        private static SelectedMemberInfo FindMatchFor(SelectedMemberInfo selectedMemberInfo, IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            var query =
                from rule in config.MatchingRules
                let match = rule.Match(selectedMemberInfo, context.Expectation, context.SelectedMemberDescription, config)
                where match != null
                select match;

            return query.FirstOrDefault();
        }
 public IEnumerable <SelectedMemberInfo> SelectMembers(
     IEnumerable <SelectedMemberInfo> selectedMembers,
     ISubjectInfo context,
     IEquivalencyAssertionOptions config)
 {
     return(selectedMembers.Except(
                config.GetSubjectType(context)
                .GetNonPrivateProperties()
                .Where(p => p.GetMethod.IsAssembly)
                .Select(SelectedMemberInfo.Create)));
 }
        private static IMember FindMatchFor(IMember selectedMember, INode currentNode, object subject,
                                            IEquivalencyAssertionOptions config)
        {
            IEnumerable <IMember> query =
                from rule in config.MatchingRules
                let match = rule.Match(selectedMember, subject, currentNode, config)
                            where match is not null
                            select match;

            return(query.FirstOrDefault());
        }
        public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config)
        {
            List<SelectedMemberInfo> members = selectedMembers.ToList();

            if (!members.Any(member => member.IsEquivalentTo(selectedMemberInfo)))
            {
                members.Add(selectedMemberInfo);
            }

            return members;
        }
        public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, ISubjectInfo context,
            IEquivalencyAssertionOptions config)
        {
            string path = context.SelectedMemberPath;
            if (!ContainsIndexingQualifiers(selectedPath))
            {
                path = RemoveInitialIndexQualifier(path);
            }

            return OnSelectMembers(selectedMembers, path, context);
        }
Exemple #23
0
        private static IEnumerable <SelectedMemberInfo> GetMembersFromExpectation(IEquivalencyValidationContext context,
                                                                                  IEquivalencyAssertionOptions config)
        {
            IEnumerable <SelectedMemberInfo> members = Enumerable.Empty <SelectedMemberInfo>();

            foreach (IMemberSelectionRule rule in config.SelectionRules)
            {
                members = rule.SelectMembers(members, context, config);
            }

            return(members);
        }
        internal IEnumerable <PropertyInfo> GetSelectedProperties(EquivalencyValidationContext context,
                                                                  IEquivalencyAssertionOptions config)
        {
            IEnumerable <PropertyInfo> properties = new List <PropertyInfo>();

            foreach (ISelectionRule selectionRule in config.SelectionRules)
            {
                properties = selectionRule.SelectProperties(properties, context);
            }

            return(properties);
        }
        internal IEnumerable <SelectedMemberInfo> GetSelectedMembers(IEquivalencyValidationContext context,
                                                                     IEquivalencyAssertionOptions config)
        {
            IEnumerable <SelectedMemberInfo> members = Enumerable.Empty <SelectedMemberInfo>();

            foreach (var selectionRule in config.SelectionRules)
            {
                members = selectionRule.SelectMembers(members, context, config);
            }

            return(members);
        }
        internal IEnumerable<SelectedMemberInfo> GetSelectedMembers(IEquivalencyValidationContext context, 
            IEquivalencyAssertionOptions config)
        {
            IEnumerable<SelectedMemberInfo> members = Enumerable.Empty<SelectedMemberInfo>();

            foreach (var selectionRule in config.SelectionRules)
            {
                members = selectionRule.SelectMembers(members, context, config);
            }

            return members;
        }
 private static void AssertMemberEquality(IEquivalencyValidationContext context, IEquivalencyValidator parent, SelectedMemberInfo selectedMemberInfo, IEquivalencyAssertionOptions config)
 {
     var matchingMember = FindMatchFor(selectedMemberInfo, context, config);
     if (matchingMember != null)
     {
         var nestedContext = context.CreateForNestedMember(selectedMemberInfo, matchingMember);
         if (nestedContext != null)
         {
             parent.AssertEqualityUsing(nestedContext);
         }
     }
 }
        internal IEnumerable<PropertyInfo> GetSelectedProperties(EquivalencyValidationContext context, 
            IEquivalencyAssertionOptions config)
        {
            IEnumerable<PropertyInfo> properties = new List<PropertyInfo>();

            foreach (ISelectionRule selectionRule in config.SelectionRules)
            {
                properties = selectionRule.SelectProperties(properties, context);
            }

            return properties;
        }
Exemple #29
0
        private static bool ShouldCompareMembersThisDeep(INode currentNode, IEquivalencyAssertionOptions options,
                                                         AssertionScope assertionScope)
        {
            bool shouldRecurse = options.AllowInfiniteRecursion || currentNode.Depth < MaxDepth;

            if (!shouldRecurse)
            {
                assertionScope.FailWith("The maximum recursion depth was reached.  ");
            }

            return(shouldRecurse);
        }
 private void AssertPropertyEquality(EquivalencyValidationContext context, IEquivalencyValidator parent, PropertyInfo propertyInfo, IEquivalencyAssertionOptions config)
 {
     var matchingProperty = FindMatchFor(propertyInfo, context, config.MatchingRules);
     if (matchingProperty != null)
     {
         EquivalencyValidationContext nestedContext = context.CreateForNestedProperty(propertyInfo, matchingProperty);
         if (nestedContext != null)
         {
             parent.AssertEqualityUsing(nestedContext);
         }
     }
 }
        internal IEnumerable <PropertyInfo> GetSelectedProperties(EquivalencyValidationContext context,
                                                                  IEquivalencyAssertionOptions config)
        {
            IEnumerable <PropertyInfo> properties = Enumerable.Empty <PropertyInfo>();

            foreach (ISelectionRule selectionRule in config.SelectionRules)
            {
                properties = selectionRule.SelectProperties(properties, context);
            }

            return(properties.Where(IsNotIndexer));
        }
Exemple #32
0
        public IEnumerable <SelectedMemberInfo> SelectMembers(IEnumerable <SelectedMemberInfo> selectedMembers, IMemberInfo context,
                                                              IEquivalencyAssertionOptions config)
        {
            string path = context.SelectedMemberPath;

            if (!ContainsIndexingQualifiers(selectedPath))
            {
                path = RemoveInitialIndexQualifier(path);
            }

            return(OnSelectMembers(selectedMembers, path, context));
        }
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            // TODO: support also for non enumerable types, if needed.
            if (!context.RuntimeType.IsClosedTypeOf(typeof(IEnumerable <>)))
            {
                return(false);
            }

            Type elementType = context.RuntimeType.GetElementType();

            return(elementType == typeof(T));
        }
        public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath,
            IEquivalencyAssertionOptions config)
        {
            var propertySelectedMemberInfo = subjectMember as PropertySelectedMemberInfo;
            if (propertySelectedMemberInfo != null)
            {
                return
                    SelectedMemberInfo.Create(obsoleteMatchingRule.Match(propertySelectedMemberInfo.PropertyInfo,
                        expectation, memberPath));
            }

            return null;
        }
Exemple #35
0
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
                           IEquivalencyAssertionOptions config)
        {
            foreach (IEquivalencyStep step in config.UserEquivalencySteps)
            {
                if (step.CanHandle(context, config) && step.Handle(context, parent, config))
                {
                    return(true);
                }
            }

            return(false);
        }
        public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyAssertionOptions config)
        {
            PropertyInfo property = subject.GetType().FindProperty(expectedMember.Name, expectedMember.Type);

            if ((property is not null) && !property.IsIndexer())
            {
                return(new Property(property, parent));
            }

            FieldInfo field = subject.GetType().FindField(expectedMember.Name, expectedMember.Type);

            return((field is not null) ? new Field(field, parent) : null);
        }
        private static IEnumerable <IMember> GetMembersFromExpectation(INode currentNode, Comparands comparands,
                                                                       IEquivalencyAssertionOptions options)
        {
            IEnumerable <IMember> members = Enumerable.Empty <IMember>();

            foreach (IMemberSelectionRule rule in options.SelectionRules)
            {
                members = rule.SelectMembers(currentNode, members,
                                             new MemberSelectionContext(comparands.CompileTimeType, comparands.RuntimeType, options));
            }

            return(members);
        }
Exemple #38
0
        public SelectedMemberInfo Match(SelectedMemberInfo subjectMember, object expectation, string memberPath,
                                        IEquivalencyAssertionOptions config)
        {
            var propertySelectedMemberInfo = subjectMember as PropertySelectedMemberInfo;

            if (propertySelectedMemberInfo != null)
            {
                return
                    (SelectedMemberInfo.Create(obsoleteMatchingRule.Match(propertySelectedMemberInfo.PropertyInfo,
                                                                          expectation, memberPath)));
            }

            return(null);
        }
Exemple #39
0
        private static IEnumerable <IMember> GetMembersFromExpectation(INode currentNode, Comparands comparands,
                                                                       IEquivalencyAssertionOptions config)
        {
            IEnumerable <IMember> members = Enumerable.Empty <IMember>();

            foreach (IMemberSelectionRule rule in config.SelectionRules)
            {
                members = rule.SelectMembers(currentNode, members,
                                             new MemberSelectionContext(comparands.CompileTimeType, comparands.RuntimeType, config));
            }

            members = members.Where(member => CandidateMembers.Contains(member.Name));

            return(members);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            IEnumerable<PropertyInfo> selectedProperties = GetSelectedProperties(context, config).ToArray();
            if (context.IsRoot && !selectedProperties.Any())
            {
                throw new InvalidOperationException("Please specify some properties to include in the comparison.");
            }

            foreach (PropertyInfo propertyInfo in selectedProperties)
            {
                AssertPropertyEquality(context, parent, propertyInfo, config);
            }

            return true;
        }
        internal static void ConfigureMatchingRules <TActual>(
            EquivalencyAssertionOptions <TActual> actualOptions,
            IEquivalencyAssertionOptions subConfigOptions)
        {
            if (subConfigOptions.MatchingRules.Any())
            {
                actualOptions.WithoutMatchingRules();
            }

            //Reverse order because Using prepends
            foreach (var matchingRule in subConfigOptions.MatchingRules.Reverse())
            {
                actualOptions.Using(new CollectionMemberMatchingRuleDecorator(matchingRule));
            }
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            if (AssertExpectationIsCollection(context.Expectation))
            {
                var validator = new EnumerableEquivalencyValidator(parent, context)
                {
                    Recursive = context.IsRoot || config.IsRecursive,
                    OrderingRules = config.OrderingRules
                };

                validator.Execute(ToArray(context.Subject), ToArray(context.Expectation));
            }

            return true;
        }
        private static void ConfigureSelectionRules <TActual>(
            EquivalencyAssertionOptions <TActual> actualOptions,
            IEquivalencyAssertionOptions subConfigOptions)
        {
            var opts = subConfigOptions;

            if (opts.SelectionRules.Any())
            {
                actualOptions.WithoutSelectionRules();
            }

            foreach (var selectionRule in opts.SelectionRules)
            {
                actualOptions.Using(new CollectionMemberSelectionRuleDecorator(selectionRule));
            }
        }
        private static IMember FindMatchFor(IMember selectedMember, INode currentNode, object subject,
                                            IEquivalencyAssertionOptions config)
        {
            IEnumerable <IMember> query =
                from rule in config.MatchingRules
                let match = rule.Match(selectedMember, subject, currentNode, config)
                            where match is not null
                            select match;

            if (config.IgnoreNonBrowsableOnSubject)
            {
                query = query.Where(member => member.IsBrowsable);
            }

            return(query.FirstOrDefault());
        }
        public IMember Match(IMember expectedMember, object subject, INode parent, IEquivalencyAssertionOptions options)
        {
            if (expectationPath.IsEquivalentTo(expectedMember.PathAndName))
            {
                var member = MemberFactory.Find(subject, subjectPath.MemberName, expectedMember.Type, parent);
                if (member is null)
                {
                    throw new ArgumentException(
                              $"Subject of type {subject?.GetType().Name} does not have member {subjectPath.MemberName}");
                }

                return(member);
            }

            return(null);
        }
Exemple #46
0
        public static AndConstraint <GenericCollectionAssertions <T> > NotContainEquivalentOf <T>(
            this GenericCollectionAssertions <T> assert,
            T expectation,
            Func <EquivalencyAssertionOptions <T>, EquivalencyAssertionOptions <T> > config,
            string because = "",
            params object[] becauseArgs)
        {
            if (ReferenceEquals(assert.Subject, null))
            {
                return(new AndConstraint <GenericCollectionAssertions <T> >(assert));
            }

            IEquivalencyAssertionOptions options     = config(AssertionOptions.CloneDefaults <T>());
            IEnumerable <object>         actualItems = assert.Subject.Cast <object>();

            using (var scope = new AssertionScope())
            {
                scope.AddReportable("configuration", options.ToString());

                foreach (var actualItem in actualItems)
                {
                    var context = new EquivalencyValidationContext
                    {
                        Subject         = actualItem,
                        Expectation     = expectation,
                        CompileTimeType = typeof(T),
                        Because         = because,
                        BecauseArgs     = becauseArgs,
                        Tracer          = options.TraceWriter,
                    };

                    var equivalencyValidator = new EquivalencyValidator(options);
                    equivalencyValidator.AssertEquality(context);

                    var failures = scope.Discard();
                    if (!failures.Any())
                    {
                        Execute.Assertion
                        .BecauseOf(because, becauseArgs)
                        .FailWith("Expected {context:collection} {0} to not contain equivalent of {1}.", assert.Subject, expectation);
                        break;
                    }
                }
            }

            return(new AndConstraint <GenericCollectionAssertions <T> >(assert));
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            Type subjectType = EnumerableEquivalencyStep.GetSubjectType(context, config);

            Type[] interfaces = GetIEnumerableInterfaces(subjectType);
            bool multipleInterfaces = (interfaces.Count() > 1);

            if (multipleInterfaces)
            {
                IEnumerable<Type> enumerableTypes = interfaces.Select(
                    type => type.GetGenericArguments().Single());

                AssertionScope.Current.FailWith(
                    String.Format(
                        "{{context:Subject}} is enumerable for more than one type.  " +
                        "It is not known which type should be use for equivalence.{0}" +
                        "IEnumerable is implemented for the following types: {1}",
                        Environment.NewLine,
                        String.Join(", ", enumerableTypes)));
            }

            if (AssertExpectationIsCollection(context.Expectation))
            {
                var validator = new EnumerableEquivalencyValidator(parent, context)
                {
                    Recursive = context.IsRoot || config.IsRecursive,
                    OrderingRules = config.OrderingRules
                };

                Type typeOfEnumeration = GetTypeOfEnumeration(subjectType);

                Expression subjectToArray = ToArray(context.Subject, typeOfEnumeration);
                Expression expectationToArray =
                    Expression.Constant(EnumerableEquivalencyStep.ToArray(context.Expectation));

                MethodCallExpression executeExpression = Expression.Call(
                    Expression.Constant(validator),
                    "Execute",
                    new Type[] { typeOfEnumeration },
                    subjectToArray,
                    expectationToArray);

                Expression.Lambda(executeExpression).Compile().DynamicInvoke();
            }

            return true;
        }
Exemple #48
0
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
                           IEquivalencyAssertionOptions config)
        {
            Type expectedType = config.GetExpectationType(context);

            var interfaceTypes = GetIEnumerableInterfaces(expectedType)
                                 .Select(type => "IEnumerable<" + type.GetGenericArguments().Single() + ">")
                                 .ToList();

            AssertionScope.Current
            .ForCondition(interfaceTypes.Count == 1)
            .FailWith("{context:Expectation} implements {0}, so cannot determine which one " +
                      "to use for asserting the equivalency of the collection. ", interfaceTypes);

            if (AssertSubjectIsCollection(context.Expectation, context.Subject))
            {
                var validator = new EnumerableEquivalencyValidator(parent, context)
                {
                    Recursive     = context.IsRoot || config.IsRecursive,
                    OrderingRules = config.OrderingRules
                };

                Type typeOfEnumeration = GetTypeOfEnumeration(expectedType);

                MethodCallExpression expectationAsArray = ToArray(context.Expectation, typeOfEnumeration);
                ConstantExpression   subjectAsArray     =
                    Expression.Constant(EnumerableEquivalencyStep.ToArray(context.Subject));

                MethodCallExpression executeExpression = Expression.Call(
                    Expression.Constant(validator),
                    ExpressionExtensions.GetMethodName(() => validator.Execute <object>(null, null)),
                    new[] { typeOfEnumeration },
                    subjectAsArray,
                    expectationAsArray);

                try
                {
                    Expression.Lambda(executeExpression).Compile().DynamicInvoke();
                }
                catch (TargetInvocationException e)
                {
                    throw e.Unwrap();
                }
            }

            return(true);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(EquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config)
        {
            if (ReferenceEquals(context.Subject, context.Expectation))
            {
                return true;
            }

            if (ReferenceEquals(context.Expectation, null))
            {
                AssertionScope.Current.FailWith(
                    "Expected {context:subject} to be {0}{reason}, but found {1}.", context.Expectation, context.Subject);

                return true;
            }

            return !ReferenceEquals(context.Subject, null) && context.Subject.Equals(context.Expectation);
        }
        public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, ISubjectInfo context, IEquivalencyAssertionOptions config)
        {
            var members = new List<SelectedMemberInfo>(selectedMembers);

            foreach (SelectedMemberInfo selectedMemberInfo in context.RuntimeType.GetNonPrivateMembers())
            {
                if (predicate(new NestedSelectionContext(context, selectedMemberInfo)))
                {
                    if (!members.Any(p => p.IsEquivalentTo(selectedMemberInfo)))
                    {
                        members.Add(selectedMemberInfo);
                    }
                }
            }

            return members;
        }
        /// <summary>
        /// Gets a value indicating whether this step can handle the current subject and/or expectation.
        /// </summary>
        public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
        {
            Type type = config.GetSubjectType(context);

            bool canHandle =
                (type != null) &&
                (type != typeof(object)) &&
                config.IsValueType(type) &&
                !type.IsArray;

            if (canHandle)
            {
                context.TraceSingle(path => $"Treating {path} as a value type");
            }

            return(canHandle);
        }
Exemple #52
0
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator
                           structuralEqualityValidator, IEquivalencyAssertionOptions config)
        {
            var version       = context.Subject as Version;
            var versionString = context.Expectation?.ToString();

            if (versionString == "<some-version>" && versionString != Version.Initial.ToString())
            {
                version.Should().NotBeNull(context.Because, context.BecauseArgs);
            }
            else
            {
                context.Subject.Should().Be(context.Expectation, context.Because, context.BecauseArgs);
            }

            return(true);
        }
        internal static void ConfigureSelectionRules <TActual>(
            EquivalencyAssertionOptions <TActual> actualOptions,
            IEquivalencyAssertionOptions subConfigOptions)
        {
            var opts = subConfigOptions;

            if (opts.SelectionRules.Any())
            {
                actualOptions.WithoutSelectionRules();
            }

            //Reverse order because Using prepends
            foreach (var selectionRule in opts.SelectionRules.Reverse())
            {
                actualOptions.Using(new CollectionMemberSelectionRuleDecorator(selectionRule));
            }
        }
        /// <summary>
        /// Asserts that an object is equivalent to another object.
        /// </summary>
        /// <remarks>
        /// Objects are equivalent when both object graphs have equally named properties with the same value,
        /// irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal.
        /// The type of a collection property is ignored as long as the collection implements <see cref="IEnumerable{T}"/> and all
        /// items in the collection are structurally equal.
        /// </remarks>
        /// <param name="config">
        /// A reference to the <see cref="EquivalencyAssertionOptions{TSubject}"/> configuration object that can be used
        /// to influence the way the object graphs are compared. You can also provide an alternative instance of the
        /// <see cref="EquivalencyAssertionOptions{TSubject}"/> class. The global defaults are determined by the
        /// <see cref="AssertionOptions"/> class.
        /// </param>
        /// <param name="because">
        /// An optional formatted phrase as is supported by <see cref="string.Format(string,object[])" /> explaining why the
        /// assertion is needed. If the phrase does not start with the word <i>because</i>, it is prepended automatically.
        /// </param>
        /// <param name="becauseArgs">
        /// Zero or more objects to format using the placeholders in <see cref="because" />.
        /// </param>
        public void BeEquivalentTo <TExpectation>(TExpectation expectation,
                                                  Func <EquivalencyAssertionOptions <TExpectation>, EquivalencyAssertionOptions <TExpectation> > config, string because = "",
                                                  params object[] becauseArgs)
        {
            IEquivalencyAssertionOptions options = config(AssertionOptions.CloneDefaults <TExpectation>());

            var context = new EquivalencyValidationContext
            {
                Subject         = Subject,
                Expectation     = expectation,
                CompileTimeType = typeof(TExpectation),
                Because         = because,
                BecauseArgs     = becauseArgs,
                Tracer          = options.TraceWriter
            };

            new EquivalencyValidator(options).AssertEquality(context);
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config)
        {
            if (!ReferenceEquals(context.Expectation, null) && !ReferenceEquals(context.Subject, null)
                && !context.Subject.GetType().IsSameOrInherits(context.Expectation.GetType()))
            {
                Type expectationType = context.Expectation.GetType();

                object convertedSubject;
                if (TryChangeType(context.Subject, expectationType, out convertedSubject))
                {
                    var newContext = context.CreateWithDifferentSubject(convertedSubject, expectationType);

                    structuralEqualityValidator.AssertEqualityUsing(newContext);
                    return true;
                }
            }

            return false;
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(EquivalencyValidationContext context, IEquivalencyValidator structuralEqualityValidator, IEquivalencyAssertionOptions config)
        {
            if (!ReferenceEquals(context.Expectation, null) && !ReferenceEquals(context.Subject, null)
                && !context.Subject.GetType().IsSameOrInherits(context.Expectation.GetType()))
            {
                try
                {
                    context.Subject = Convert.ChangeType(context.Subject, context.Expectation.GetType(), CultureInfo.CurrentCulture);
                }
                catch (FormatException)
                {
                }
                catch (InvalidCastException)
                {
                }
            }

            return false;
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
            IEquivalencyAssertionOptions config)
        {
            switch (config.EnumEquivalencyHandling)
            {
                case EnumEquivalencyHandling.ByValue:
                    CompareByValue(context);
                    break;
                case EnumEquivalencyHandling.ByName:
                    context.Subject.ToString()
                        .Should()
                        .Be(context.Expectation.ToString(), context.Reason, context.ReasonArgs);
                    break;
                default:
                    throw new InvalidOperationException(string.Format("Don't know how to handle {0}",
                        config.EnumEquivalencyHandling));
            }

            return true;
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(EquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            IEnumerable<PropertyInfo> selectedProperties = GetSelectedProperties(context, config).ToArray();
            if (context.IsRoot && !selectedProperties.Any())
            {
                throw new InvalidOperationException("Please specify some properties to include in the comparison.");
            }

            bool expectationIsNotNull = AssertionScope.Current
                .ForCondition(!ReferenceEquals(context.Expectation, null))
                .FailWith("Expected {context:subject} to be <null>, but found {0}.", context.Subject);

            if (expectationIsNotNull)
            {
                foreach (PropertyInfo propertyInfo in selectedProperties)
                {
                    AssertPropertyEquality(context, parent, propertyInfo, config);
                }
            }
            return true;
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent,
            IEquivalencyAssertionOptions config)
        {
            Type subjectType = config.GetSubjectType(context);

            var interfaceTypes = GetIEnumerableInterfaces(subjectType)
                .Select(type => "IEnumerable<" + type.GetGenericArguments().Single() + ">")
                .ToList();

            AssertionScope.Current
                .ForCondition(interfaceTypes.Count() == 1)
                .FailWith("{context:Subject} implements {0}, so cannot determine which one " +
                          "to use for asserting the equivalency of the collection. ", interfaceTypes);

            if (AssertExpectationIsCollection(context.Expectation, context.Subject))
            {
                var validator = new EnumerableEquivalencyValidator(parent, context)
                {
                    Recursive = context.IsRoot || config.IsRecursive,
                    OrderingRules = config.OrderingRules
                };

                Type typeOfEnumeration = GetTypeOfEnumeration(subjectType);

                Expression subjectToArray = ToArray(context.Subject, typeOfEnumeration);
                Expression expectationToArray =
                    Expression.Constant(EnumerableEquivalencyStep.ToArray(context.Expectation));

                MethodCallExpression executeExpression = Expression.Call(
                    Expression.Constant(validator),
                    ExpressionExtensions.GetMethodName(() => validator.Execute<object>(null, null)),
                    new[] {typeOfEnumeration},
                    subjectToArray,
                    expectationToArray);

                Expression.Lambda(executeExpression).Compile().DynamicInvoke();
            }

            return true;
        }
        /// <summary>
        /// Applies a step as part of the task to compare two objects for structural equality.
        /// </summary>
        /// <value>
        /// Should return <c>true</c> if the subject matches the expectation or if no additional assertions
        /// have to be executed. Should return <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// May throw when preconditions are not met or if it detects mismatching data.
        /// </remarks>
        public virtual bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
        {
            var subject = (IDictionary)context.Subject;
            var expectation = context.Expectation as IDictionary;

            if (PreconditionsAreMet(context, expectation, subject))
            {
                foreach (object key in subject.Keys)
                {
                    if (config.IsRecursive)
                    {
                        parent.AssertEqualityUsing(context.CreateForDictionaryItem(key, subject[key], expectation[key]));
                    }
                    else
                    {
                        subject[key].Should().Be(expectation[key], context.Reason, context.ReasonArgs);
                    }
                }
            }

            return true;
        }