public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { Type expectationType = comparands.GetExpectedType(context.Options); EqualityStrategy strategy = context.Options.GetEqualityStrategy(expectationType); bool canHandle = (strategy == EqualityStrategy.Equals) || (strategy == EqualityStrategy.ForceEquals); if (canHandle) { context.Tracer.WriteLine(member => { string strategyName = (strategy == EqualityStrategy.Equals) ? "Equals must be used" : "object overrides Equals"; return($"Treating {member.Description} as a value type because {strategyName}."); }); comparands.Subject.Should().Be(comparands.Expectation, context.Reason.FormattedMessage, context.Reason.Arguments); return(EquivalencyResult.AssertionCompleted); } else { return(EquivalencyResult.ContinueWithNext); } }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (!context.Options.ConversionSelector.RequiresConversion(comparands, context.CurrentNode)) { return(EquivalencyResult.ContinueWithNext); } if ((comparands.Expectation is null) || (comparands.Subject is null)) { return(EquivalencyResult.ContinueWithNext); } Type subjectType = comparands.Subject.GetType(); Type expectationType = comparands.Expectation.GetType(); if (subjectType.IsSameOrInherits(expectationType)) { return(EquivalencyResult.ContinueWithNext); } if (TryChangeType(comparands.Subject, expectationType, out object convertedSubject)) { context.Tracer.WriteLine(member => Invariant($"Converted subject {comparands.Subject} at {member.Description} to {expectationType}")); comparands.Subject = convertedSubject; } else { context.Tracer.WriteLine(member => Invariant($"Subject {comparands.Subject} at {member.Description} could not be converted to {expectationType}")); } return(EquivalencyResult.ContinueWithNext); }
private static void AssertDictionaryEquivalence(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator parent, DictionaryInterfaceInfo actualDictionary, DictionaryInterfaceInfo expectedDictionary) { AssertDictionaryEquivalenceMethod .MakeGenericMethod(actualDictionary.Key, actualDictionary.Value, expectedDictionary.Key, expectedDictionary.Value) .Invoke(null, new[] { context, parent, context.Options, comparands.Subject, comparands.Expectation }); }
/// <summary> /// Asserts that an instance of <see cref="DataSet"/> is equivalent to another. /// </summary> /// <remarks> /// Data sets are equivalent when their <see cref="DataSet.Tables"/> and <see cref="DataSet.ExtendedProperties"/> /// collections are equivalent and the following members have the same values: /// /// <list type="bullet"> /// <item><description>DataSetName</description></item> /// <item><description>CaseSensitive</description></item> /// <item><description>EnforceConstraints</description></item> /// <item><description>HasErrors</description></item> /// <item><description>Locale</description></item> /// <item><description>Namespace</description></item> /// <item><description>Prefix</description></item> /// <item><description>RemotingFormat</description></item> /// <item><description>SchemaSerializationMode</description></item> /// </list> /// /// The <see cref="DataSet"/> objects must be of the same type; if two <see cref="DataSet"/> objects /// are equivalent in all ways, except that one is a custom subclass of <see cref="DataSet"/> (e.g. to provide /// typed accessors for <see cref="DataTable"/> values contained by the <see cref="DataSet"/>), then by default, /// they will not be considered equivalent. /// /// This, as well as testing of any property can be overridden using the <paramref name="config"/> callback. /// By calling <see cref="IDataEquivalencyAssertionOptions{T}.AllowingMismatchedTypes"/>, two <see cref="DataSet"/> /// objects of differing types can be considered equivalent. This setting applies to all types recursively tested /// as part of the <see cref="DataSet"/>. /// /// Exclude specific properties using <see cref="IDataEquivalencyAssertionOptions{T}.Excluding(System.Linq.Expressions.Expression{Func{T, object}})"/>. /// Exclude specific tables within the data set using <see cref="IDataEquivalencyAssertionOptions{T}.ExcludingTable(string)"/> /// or a related function. You can also indicate that columns should be excluded within the <see cref="DataTable"/> /// objects recursively tested as part of the <see cref="DataSet"/> using <see cref="IDataEquivalencyAssertionOptions{T}.ExcludingColumn(DataColumn)"/> /// or a related function. The <see cref="IDataEquivalencyAssertionOptions{T}.ExcludingColumnInAllTables(string)"/> method /// can be used to exclude columns across all <see cref="DataTable"/> objects in the <see cref="DataSet"/> that share /// the same name. /// /// You can use <see cref="IDataEquivalencyAssertionOptions{T}.ExcludingRelated(System.Linq.Expressions.Expression{Func{DataTable, object}})"/> /// and related functions to exclude properties on other related System.Data types. /// </remarks> /// <param name="expectation">A <see cref="DataColumn"/> with the expected configuration.</param> /// <param name="config"> /// A reference to the <see cref="IDataEquivalencyAssertionOptions{DataSet}"/> 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="IDataEquivalencyAssertionOptions{DataSet}"/> class. The global defaults are determined by the /// <see cref="AssertionOptions"/> class. /// </param> /// <param name="because"> /// A 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 <paramref name="because"/>. /// </param> public AndConstraint <DataSetAssertions <TDataSet> > BeEquivalentTo(DataSet expectation, Func <IDataEquivalencyAssertionOptions <DataSet>, IDataEquivalencyAssertionOptions <DataSet> > config, string because = "", params object[] becauseArgs) { Guard.ThrowIfArgumentIsNull(config, nameof(config)); IDataEquivalencyAssertionOptions <DataSet> options = config(AssertionOptions.CloneDefaults <DataSet, DataEquivalencyAssertionOptions <DataSet> >(e => new(e))); var comparands = new Comparands { Subject = Subject, Expectation = expectation, CompileTimeType = typeof(TDataSet) }; var context = new EquivalencyValidationContext(Node.From <DataSet>(() => AssertionScope.Current.CallerIdentity), options) { Reason = new Reason(because, becauseArgs), TraceWriter = options.TraceWriter, }; var equivalencyValidator = new EquivalencyValidator(); equivalencyValidator.AssertEquality(comparands, context); return(new AndConstraint <DataSetAssertions <TDataSet> >(this)); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var subject = comparands.Subject as IDictionary; var expectation = comparands.Expectation as IDictionary; if (PreconditionsAreMet(expectation, subject)) { if (expectation is not null) { foreach (object key in expectation.Keys) { if (context.Options.IsRecursive) { context.Tracer.WriteLine(member => Invariant($"Recursing into dictionary item {key} at {member.Description}")); nestedValidator.RecursivelyAssertEquality(new Comparands(subject[key], expectation[key], typeof(object)), context.AsDictionaryItem <object, IDictionary>(key)); } else { context.Tracer.WriteLine(member => Invariant($"Comparing dictionary item {key} at {member.Description} between subject and expectation")); subject[key].Should().Be(expectation[key], context.Reason.FormattedMessage, context.Reason.Arguments); } } } } return(EquivalencyResult.AssertionCompleted); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var subject = comparands.Subject as DataColumn; var expectation = comparands.Expectation as DataColumn; if (expectation is null) { if (subject is not null) { AssertionScope.Current.FailWith("Expected {context:DataColumn} value to be null, but found {0}", subject); } } else { if (subject is null) { if (comparands.Subject is null) { AssertionScope.Current.FailWith("Expected {context:DataColumn} to be non-null, but found null"); } else { AssertionScope.Current.FailWith("Expected {context:DataColumn} to be of type {0}, but found {1} instead", expectation.GetType(), comparands.Subject.GetType()); } } else { CompareSubjectAndExpectationOfTypeDataColumn(comparands, context, nestedValidator, subject); } } return(EquivalencyResult.AssertionCompleted); }
private static void CompareSubjectAndExpectationOfTypeDataColumn(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator parent, DataColumn subject) { bool compareColumn = true; var dataSetConfig = context.Options as DataEquivalencyAssertionOptions <DataSet>; var dataTableConfig = context.Options as DataEquivalencyAssertionOptions <DataTable>; var dataColumnConfig = context.Options as DataEquivalencyAssertionOptions <DataColumn>; if ((dataSetConfig?.ShouldExcludeColumn(subject) == true) || (dataTableConfig?.ShouldExcludeColumn(subject) == true) || (dataColumnConfig?.ShouldExcludeColumn(subject) == true)) { compareColumn = false; } if (compareColumn) { foreach (IMember expectationMember in GetMembersFromExpectation(context.CurrentNode, comparands, context.Options)) { if (expectationMember.Name != nameof(subject.Table)) { CompareMember(expectationMember, comparands, parent, context); } } } }
public ObjectInfo(Comparands comparands, INode currentNode) { Type = currentNode.Type; Path = currentNode.PathAndName; CompileTimeType = comparands.CompileTimeType; RuntimeType = comparands.RuntimeType; }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { Type expectationType = comparands.GetExpectedType(context.Options); if (expectationType is null || expectationType != typeof(string)) { return(EquivalencyResult.ContinueWithNext); } if (!ValidateAgainstNulls(comparands, context.CurrentNode)) { return(EquivalencyResult.AssertionCompleted); } bool subjectIsString = ValidateSubjectIsString(comparands, context.CurrentNode); if (subjectIsString) { string subject = (string)comparands.Subject; string expectation = (string)comparands.Expectation; subject.Should() .Be(expectation, context.Reason.FormattedMessage, context.Reason.Arguments); } return(EquivalencyResult.AssertionCompleted); }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Expectation is DateTime time) { throw new Exception("Failed"); } return(EquivalencyResult.ContinueWithNext); }
internal static AssertionContext <TSubject> CreateFrom(Comparands comparands, IEquivalencyValidationContext context) { return(new( context.CurrentNode, (TSubject)comparands.Subject, (TSubject)comparands.Expectation, context.Reason.FormattedMessage, context.Reason.Arguments)); }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (!typeof(T).IsAssignableFrom(comparands.GetExpectedType(context.Options))) { return(EquivalencyResult.ContinueWithNext); } return(OnHandle(comparands, context, nestedValidator)); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var subject = (XDocument)comparands.Subject; var expectation = (XDocument)comparands.Expectation; subject.Should().BeEquivalentTo(expectation, context.Reason.FormattedMessage, context.Reason.Arguments); return(EquivalencyResult.AssertionCompleted); }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Expectation is DateTime time) { ((DateTime)comparands.Subject).Should().BeCloseTo(time, 1.Minutes()); return(EquivalencyResult.AssertionCompleted); } return(EquivalencyResult.ContinueWithNext); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var subject = comparands.Subject as DataSet; if (comparands.Expectation is not DataSet expectation) { if (subject is not null) { AssertionScope.Current.FailWith("Expected {context:DataSet} value to be null, but found {0}", subject); } }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (!context.Options.IsRecursive && !context.CurrentNode.IsRoot) { comparands.Subject.Should().Be(comparands.Expectation, context.Reason.FormattedMessage, context.Reason.Arguments); return(EquivalencyResult.AssertionCompleted); } return(EquivalencyResult.ContinueWithNext); }
private static bool ValidateSubjectIsString(Comparands comparands, INode currentNode) { if (comparands.Subject is string) { return(true); } return (AssertionScope.Current .FailWith($"Expected {currentNode} to be {{0}}, but found {{1}}.", comparands.RuntimeType, comparands.Subject.GetType())); }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { foreach (IEquivalencyStep step in context.Options.UserEquivalencySteps) { if (step.Handle(comparands, context, nestedValidator) == EquivalencyResult.AssertionCompleted) { return(EquivalencyResult.AssertionCompleted); } } return(EquivalencyResult.ContinueWithNext); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var subject = comparands.Subject as DataRow; var expectation = comparands.Expectation as DataRow; if (expectation is null) { if (subject is not null) { AssertionScope.Current.FailWith("Expected {context:DataRow} value to be null, but found {0}", subject); } } else { if (subject is null) { if (comparands.Subject is null) { AssertionScope.Current.FailWith("Expected {context:DataRow} to be non-null, but found null"); } else { AssertionScope.Current.FailWith("Expected {context:DataRow} to be of type {0}, but found {1} instead", expectation.GetType(), comparands.Subject.GetType()); } } else { var dataSetConfig = context.Options as DataEquivalencyAssertionOptions <DataSet>; var dataTableConfig = context.Options as DataEquivalencyAssertionOptions <DataTable>; var dataRowConfig = context.Options as DataEquivalencyAssertionOptions <DataRow>; if (dataSetConfig?.AllowMismatchedTypes != true && dataTableConfig?.AllowMismatchedTypes != true && dataRowConfig?.AllowMismatchedTypes != true) { AssertionScope.Current .ForCondition(subject.GetType() == expectation.GetType()) .FailWith("Expected {context:DataRow} to be of type '{0}'{reason}, but found '{1}'", expectation.GetType(), subject.GetType()); } SelectedDataRowMembers selectedMembers = GetMembersFromExpectation(comparands, context.CurrentNode, context.Options); CompareScalarProperties(subject, expectation, selectedMembers); CompareFieldValues(context, nestedValidator, subject, expectation, dataSetConfig, dataTableConfig, dataRowConfig); } } return(EquivalencyResult.AssertionCompleted); }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Subject is not DataRowCollection) { AssertionScope.Current .FailWith("Expected {context:value} to be of type DataRowCollection, but found {0}", comparands.Subject.GetType()); } else { RowMatchMode rowMatchMode = RowMatchMode.Index; if (context.Options is DataEquivalencyAssertionOptions <DataSet> dataSetConfig) { rowMatchMode = dataSetConfig.RowMatchMode; } else if (context.Options is DataEquivalencyAssertionOptions <DataTable> dataTableConfig) { rowMatchMode = dataTableConfig.RowMatchMode; } var subject = (DataRowCollection)comparands.Subject; var expectation = (DataRowCollection)comparands.Expectation; bool success = AssertionScope.Current .ForCondition(subject.Count == expectation.Count) .FailWith("Expected {context:DataRowCollection} to contain {0} row(s){reason}, but found {1}", expectation.Count, subject.Count); if (success) { switch (rowMatchMode) { case RowMatchMode.Index: MatchRowsByIndexAndCompare(context, nestedValidator, subject, expectation); break; case RowMatchMode.PrimaryKey: MatchRowsByPrimaryKeyAndCompare(nestedValidator, context, subject, expectation); break; default: AssertionScope.Current.FailWith( "Unknown RowMatchMode {0} when trying to compare {context:DataRowCollection}", rowMatchMode); break; } } } return(EquivalencyResult.AssertionCompleted); }
private static IEnumerable <IMember> GetMembersFromExpectation(Comparands comparands, INode contextCurrentNode, IEquivalencyAssertionOptions options) { IEnumerable <IMember> members = Enumerable.Empty <IMember>(); foreach (IMemberSelectionRule rule in options.SelectionRules) { members = rule.SelectMembers(contextCurrentNode, members, new MemberSelectionContext(comparands.CompileTimeType, comparands.RuntimeType, options)); } return(members); }
private static bool AssertSameLength(Comparands comparands, DictionaryInterfaceInfo actualDictionary, DictionaryInterfaceInfo expectedDictionary) { if (comparands.Subject is ICollection subjectCollection && comparands.Expectation is ICollection expectationCollection && subjectCollection.Count == expectationCollection.Count) { return(true); } return((bool)AssertSameLengthMethod .MakeGenericMethod(actualDictionary.Key, actualDictionary.Value, expectedDictionary.Key, expectedDictionary.Value) .Invoke(null, new[] { comparands.Subject, comparands.Expectation })); }
public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { var canHandle = comparands.Subject?.GetType().IsAssignableTo(typeof(JToken)) ?? false; if (!canHandle) { return(EquivalencyResult.ContinueWithNext); } ((JToken)comparands.Subject !).Should().BeEquivalentTo( (JToken)comparands.Expectation, context.Reason.FormattedMessage, context.Reason.Arguments); return(EquivalencyResult.AssertionCompleted); }
public void When_stringifying_a_validation_context_it_should_ignore_culture() { // Arrange var comparands = new Comparands { Subject = 1.234, Expectation = 5.678 }; // Act var str = comparands.ToString(); // Assert str.Should().Match("*1.234*5.678*", "it should always use . as decimal separator"); }
private static void HandleByValue(Comparands comparands) { decimal?subjectsUnderlyingValue = ExtractDecimal(comparands.Subject); decimal?expectationsUnderlyingValue = ExtractDecimal(comparands.Expectation); Execute.Assertion .ForCondition(subjectsUnderlyingValue == expectationsUnderlyingValue) .FailWith(() => { string subjectsName = GetDisplayNameForEnumComparison(comparands.Subject, subjectsUnderlyingValue); string expectationName = GetDisplayNameForEnumComparison(comparands.Expectation, expectationsUnderlyingValue); return(new FailReason($"Expected {{context:enum}} to equal {expectationName} by value{{reason}}, but found {subjectsName}.")); }); }
private static bool ValidateAgainstNulls(Comparands comparands, INode currentNode) { object expected = comparands.Expectation; object subject = comparands.Subject; bool onlyOneNull = (expected is null) != (subject is null); if (onlyOneNull) { AssertionScope.Current.FailWith( $"Expected {currentNode.Description} to be {{0}}{{reason}}, but found {{1}}.", expected, subject); return(false); } return(true); }
private static void AssertMemberEquality(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator parent, IMember selectedMember, IEquivalencyAssertionOptions options) { IMember matchingMember = FindMatchFor(selectedMember, context.CurrentNode, comparands.Subject, options); if (matchingMember is not null) { var nestedComparands = new Comparands { Subject = matchingMember.GetValue(comparands.Subject), Expectation = selectedMember.GetValue(comparands.Expectation), CompileTimeType = selectedMember.Type }; parent.RecursivelyAssertEquality(nestedComparands, context.AsNestedMember(selectedMember)); } }
#pragma warning restore SA1110 public EquivalencyResult Handle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Expectation != null) { Type expectationType = comparands.GetExpectedType(context.Options); bool isDictionary = DictionaryInterfaceInfo.TryGetFrom(expectationType, "expectation", out var expectedDictionary); if (isDictionary) { Handle(comparands, expectedDictionary, context, nestedValidator); return(EquivalencyResult.AssertionCompleted); } } return(EquivalencyResult.ContinueWithNext); }
private static void Handle(Comparands comparands, DictionaryInterfaceInfo expectedDictionary, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (AssertSubjectIsNotNull(comparands.Subject) && AssertExpectationIsNotNull(comparands.Subject, comparands.Expectation)) { var(isDictionary, actualDictionary) = EnsureSubjectIsDictionary(comparands, expectedDictionary); if (isDictionary) { if (AssertSameLength(comparands, actualDictionary, expectedDictionary)) { AssertDictionaryEquivalence(comparands, context, nestedValidator, actualDictionary, expectedDictionary); } } } }
protected override EquivalencyResult OnHandle(Comparands comparands, IEquivalencyValidationContext context, IEquivalencyValidator nestedValidator) { if (comparands.Subject is not ConstraintCollection) { AssertionScope.Current .FailWith("Expected a value of type ConstraintCollection at {context:Constraints}, but found {0}", comparands.Subject.GetType()); } else { var subject = (ConstraintCollection)comparands.Subject; var expectation = (ConstraintCollection)comparands.Expectation; var subjectConstraints = subject.Cast <Constraint>().ToDictionary(constraint => constraint.ConstraintName); var expectationConstraints = expectation.Cast <Constraint>().ToDictionary(constraint => constraint.ConstraintName); IEnumerable <string> constraintNames = subjectConstraints.Keys.Union(expectationConstraints.Keys); foreach (var constraintName in constraintNames) { AssertionScope.Current .ForCondition(subjectConstraints.TryGetValue(constraintName, out Constraint subjectConstraint)) .FailWith("Expected constraint named {0} in {context:Constraints collection}{reason}, but did not find one", constraintName); AssertionScope.Current .ForCondition(expectationConstraints.TryGetValue(constraintName, out Constraint expectationConstraint)) .FailWith("Found unexpected constraint named {0} in {context:Constraints collection}", constraintName); if ((subjectConstraint is not null) && (expectationConstraint is not null)) { Comparands newComparands = new() { Subject = subjectConstraint, Expectation = expectationConstraint, CompileTimeType = typeof(Constraint) }; IEquivalencyValidationContext nestedContext = context.AsCollectionItem <Constraint>(constraintName); nestedValidator.RecursivelyAssertEquality(newComparands, nestedContext); } } } return(EquivalencyResult.AssertionCompleted); } }