/// <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));
        }
        /// <summary>
        /// Asserts that a collection of objects is equivalent to another collection of objects.
        /// </summary>
        /// <remarks>
        /// The two collections are equivalent when they both contain the same strings in any order.
        /// </remarks>
        /// <param name="config">
        /// A reference to the <see cref="EquivalencyAssertionOptions{String}"/> 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{String}"/> 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 AndConstraint <StringCollectionAssertions> BeEquivalentTo(IEnumerable <string> expectation,
                                                                         Func <EquivalencyAssertionOptions <string>, EquivalencyAssertionOptions <string> > config, string because = "",
                                                                         params object[] becauseArgs)
        {
            Guard.ThrowIfArgumentIsNull(config, nameof(config));

            EquivalencyAssertionOptions <IEnumerable <string> > options = config(AssertionOptions.CloneDefaults <string>()).AsCollection();

            var context = new EquivalencyValidationContext
            {
                Subject          = Subject,
                Expectation      = expectation,
                RootIsCollection = true,
                CompileTimeType  = typeof(IEnumerable <string>),
                Because          = because,
                BecauseArgs      = becauseArgs,
                Tracer           = options.TraceWriter
            };

            var equivalencyValidator = new EquivalencyValidator(options);

            equivalencyValidator.AssertEquality(context);

            return(new AndConstraint <StringCollectionAssertions>(this));
        }
示例#3
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>
        /// 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
            };

            var equivalencyValidator = new EquivalencyValidator(options);

            equivalencyValidator.AssertEquality(context);
        }
示例#5
0
        /// <summary>
        /// Asserts that a collection of objects is equivalent to another collection of objects.
        /// </summary>
        /// <remarks>
        /// Objects within the collections 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"/> 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(IEnumerable expectation,
                                   Func <EquivalencyAssertionOptions <IEnumerable>, EquivalencyAssertionOptions <IEnumerable> > config, string because = "",
                                   params object[] becauseArgs)
        {
            EquivalencyAssertionOptions <IEnumerable> options = config(AssertionOptions.CloneDefaults <IEnumerable>());

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

            var equivalencyValidator = new EquivalencyValidator(options);

            equivalencyValidator.AssertEquality(context);
        }
 public static void ShouldNotBeEquivalentToDefault<T>( this T subject, 
     Func<EquivalencyAssertionOptions<T>, EquivalencyAssertionOptions<T>> config, string because = "", params object[] reasonArgs )
 {
     var context = new EquivalencyValidationContext
     {
         Subject = subject,
         Expectation = subject,
         CompileTimeType = typeof( T ),
         Reason = because,
         ReasonArgs = reasonArgs
     };
     var validator = new EquivalencyValidator( 
         config( EquivalencyAssertionOptions<T>.Default()
             .Using<string>( ctx => ctx.Subject.Should().NotBeDefault() ).WhenTypeIs<string>() )
             .WithStrictOrdering()
             );
     validator.Steps.Remove( validator.Steps.Single( _ => typeof( TryConversionEquivalencyStep ) == _.GetType() ) );
     validator.Steps.Remove( validator.Steps.Single( _ => typeof( ReferenceEqualityEquivalencyStep ) == _.GetType() ) );
     validator.Steps.Remove( validator.Steps.Single( _ => typeof( SimpleEqualityEquivalencyStep ) == _.GetType() ) );
     validator.Steps.Add( new SimpleIsNotDefaultEquivalencyStep() );
 
     validator.AssertEquality( context );
 }