예제 #1
0
        public void DateTimeGenerationStabilityTest()
        {
            // Arrange
            var testingGen1 = _factory.CreateDateTimeGenerator(_seed);
            var testingGen2 = _factory.CreateDateTimeGenerator(_seed);

            // Act
            var value1 = testingGen1.GetNext();
            var value2 = testingGen2.GetNext();

            value1.Should().Be(value2);
        }
예제 #2
0
        private void InitializeGenerators()
        {
            _randomLengthGenerator = _generatorFactory.CreateCollectionSizeGenerator(_seed);

            if (TypeCheckExtensions.IsTypeNumericOrChar(_typeParameter))
            {
                _randomValueGenerator = _generatorFactory.CreateNumericGenerator(_seed);
            }
            else if (_typeParameter == typeof(string))
            {
                _randomValueGenerator = _generatorFactory.CreateStringGenerator(_seed);
            }
            else if (_typeParameter == typeof(bool))
            {
                _randomValueGenerator = _generatorFactory.CreateBooleanGenerator(_seed);
            }
            else if (_typeParameter == typeof(DateTime))
            {
                _randomValueGenerator = _generatorFactory.CreateDateTimeGenerator(_seed);
            }

            // Just for sake of not making this too complicated let's assume that if a type
            // implements IEnumerable then it's a collection
            // We've also already checked if the type is string, so it's safe to just check IEnumerable
            else if (_depthLimit >= 0 && _typeParameter.GetInterface(nameof(IEnumerable)) != null)
            {
                _randomValueGenerator = _generatorFactory.CreateCollectionGenerator(_typeParameter, (int)(_seed + _depthLimit), _depthLimit);
            }

            else if (_depthLimit > 0 && _typeParameter.IsClass && !(typeof(Delegate).IsAssignableFrom(_typeParameter)) && _typeParameter.GetConstructor(Type.EmptyTypes) != null)
            {
                _randomValueGenerator = _generatorFactory.CreateObjectGenerator(_typeParameter, _seed, _depthLimit - 1);
            }

            // We can't assign value types other than we know about or types without a parameterless constructor
            else
            {
                _randomValueGenerator = null;
            }
        }
예제 #3
0
        private void InitializeGenerators()
        {
            // 1. Filter out all read only props, we cannot assign them anyway
            props = props.Where(p => p.CanWrite);

            #region Navigation props generators
            navigationPropertiesGenerators = new Dictionary <PropertyInfo, RandomValueGenerator>();

            // 2. Try to find navigation properties (properties with a foreign key

            navigationPropertiesWithFk = new Dictionary <PropertyInfo, PropertyInfo>();

            if (_depthLimit > 0)
            {
                List <PropertyInfo> foreignKeyProps;

                // Method A: via ForeignKeyAttribute
                foreignKeyProps = props.Where(p => p.GetCustomAttribute <ForeignKeyAttribute>() != null).ToList();
                foreach (var prop in foreignKeyProps)
                {
                    var attr           = prop.GetCustomAttribute <ForeignKeyAttribute>();
                    var navigationProp = foreignKeyProps.FirstOrDefault(p => p.Name == attr.Name);

                    // If the navigation property wasn't found
                    // (which can happen since it's not checked compile-time)
                    // we remove it from the list of props that are foreign key ID
                    if (navigationProp != null)
                    {
                        // Check if the type of navigation property really contains the field "ID" (case insensitive)
                        var idProp = navigationProp.PropertyType.GetProperties().FirstOrDefault(p => p.Name.ToLower() == "id");
                        if (idProp != null)
                        {
                            var generatorType = typeof(RandomObjectGenerator <>).MakeGenericType(typeof(T));
                            var generator     = (RandomValueGenerator)Activator.CreateInstance(generatorType, _masterSeed + GetAdditionalSeed <T>(navigationProp), _depthLimit - 1);
                            navigationPropertiesGenerators.Add(navigationProp, generator);
                            navigationPropertiesWithFk.Add(navigationProp, prop);
                        }
                        else
                        {
                            foreignKeyProps.Remove(prop);
                        }
                    }
                    else
                    {
                        foreignKeyProps.Remove(prop);
                    }
                }

                props = props.Except(navigationPropertiesWithFk.Keys);
                props = props.Except(navigationPropertiesWithFk.Values);

                // Method B: via checking the names

                // Get properties, types of which are classes (excluding string)
                var classProps = props.Where(p => p.PropertyType != typeof(string) && p.PropertyType.IsClass);
                foreach (var prop in classProps)
                {
                    var fkProp = props.FirstOrDefault(p => $"{prop.Name}Id".ToLower() == p.Name.ToLower());
                    if (fkProp != null && (prop.PropertyType
                                           .GetProperties()
                                           .FirstOrDefault(p => p.Name.ToLower() == "id") != null))
                    {
                        var generatorType = typeof(RandomObjectGenerator <>).MakeGenericType(prop.PropertyType);
                        var generator     = (RandomValueGenerator)Activator.CreateInstance(generatorType, _masterSeed + GetAdditionalSeed <T>(prop), _depthLimit - 1);
                        navigationPropertiesGenerators.Add(prop, generator);
                        navigationPropertiesWithFk.Add(prop, fkProp);
                    }
                }

                props = props.Except(navigationPropertiesWithFk.Keys);
                props = props.Except(navigationPropertiesWithFk.Values);
            }

            #endregion

            #region Collection navigation props generators



            #endregion

            #region Primitive props generators

            // 3. Assign generators to properties with "primitive" types

            // 3.1 Numeric props
            numericValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator <double> >();

            var numericProps = props.Where(p => TypeCheckExtensions.IsTypeNumericOrChar(p.PropertyType));

            foreach (var prop in numericProps)
            {
                var additionalSeed = GetAdditionalSeed <T>(prop);

                numericValueGenerators.Add(prop, _factory.CreateNumericGenerator(_masterSeed + additionalSeed));
            }

            // 3.2 String props
            stringValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator <string> >();

            var stringProps = props.Where(p => p.PropertyType == typeof(string));

            foreach (var prop in stringProps)
            {
                var additionalSeed = GetAdditionalSeed <T>(prop);

                stringValueGenerators.Add(prop, _factory.CreateStringGenerator(_masterSeed + additionalSeed));
            }

            props = props.Except(stringProps).ToList();

            // 3.3 Boolean props
            booleanValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator <bool> >();

            var booleanProps = props.Where(p => p.PropertyType == typeof(bool));

            foreach (var prop in booleanProps)
            {
                var additionalSeed = GetAdditionalSeed <T>(prop);

                booleanValueGenerators.Add(prop, _factory.CreateBooleanGenerator(_masterSeed + additionalSeed));
            }

            props = props.Except(booleanProps).ToList();

            // 3.4 DateTime props
            dateTimeValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator <DateTime> >();

            var dateTimeProps = props.Where(p => p.PropertyType == typeof(DateTime));

            foreach (var prop in dateTimeProps)
            {
                var additionalSeed = GetAdditionalSeed <T>(prop);

                dateTimeValueGenerators.Add(prop, _factory.CreateDateTimeGenerator(_masterSeed + additionalSeed));
            }

            props = props.Except(dateTimeProps).ToList();

            #endregion

            #region Collection props generators

            // 4. Assign generators to collection props
            collectionValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator>();

            if (_depthLimit >= 0)
            {
                // We already excluded all props of type string, so we can safely
                // check only for IEnumerable
                var collectionProps = props.Where(p => p.PropertyType.GetInterface(nameof(IEnumerable)) != null);

                foreach (var prop in collectionProps)
                {
                    var additionalSeed = GetAdditionalSeed <T>(prop);

                    var generatorType = typeof(RandomCollectionGenerator <>).MakeGenericType(prop.PropertyType);
                    var generator     = (RandomValueGenerator)Activator.CreateInstance(generatorType, _masterSeed + additionalSeed, _depthLimit - 1);

                    collectionValueGenerators.Add(prop, generator);
                }
            }
            #endregion

            #region Other props generators
            // 5. Leave all props that we can easily assign at runtime - which have a constructor with no parameters
            objectValueGenerators = new Dictionary <PropertyInfo, RandomValueGenerator>();

            if (_depthLimit >= 1)
            {
                props = props.Where(p => p.PropertyType.GetConstructor(Type.EmptyTypes) != null);
                foreach (var prop in props)
                {
                    var additionalSeed = GetAdditionalSeed <T>(prop);

                    var generatorType = typeof(RandomObjectGenerator <>).MakeGenericType(prop.PropertyType);
                    var generator     = (RandomValueGenerator)Activator.CreateInstance(generatorType, additionalSeed, _depthLimit - 1);
                    objectValueGenerators.Add(prop, generator);
                }
            }

            #endregion
        }