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); }
/// <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); }
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; }
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)); }
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; }
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); }
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); }
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); }
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; }
/// <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); }
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; }