public void PopulateThrowsExceptionWhenProcessorReturnsNull()
        {
            var model        = new SlimModel();
            var buildHistory = new BuildHistory();

            var processor          = Substitute.For <IBuildProcessor>();
            var buildConfiguration = Substitute.For <IBuildConfiguration>();
            var typeCapability     = Substitute.For <IBuildCapability>();

            typeCapability.SupportsCreate.Returns(true);
            typeCapability.SupportsPopulate.Returns(true);
            typeCapability.ImplementedByType.Returns(typeof(DummyTypeCreator));

            var sut = new DefaultExecuteStrategy(buildHistory, _buildLog, processor);

            processor.GetBuildCapability(sut, Arg.Any <BuildRequirement>(),
                                         typeof(SlimModel))
            .Returns(typeCapability);

            sut.Initialize(buildConfiguration);

            Action action = () => sut.Populate(model);

            action.Should().Throw <BuildException>();
        }
        public void PopulateThrowsExceptionWhenNotInitialized()
        {
            var value = new Person();

            var sut = new DefaultExecuteStrategy();

            Action action = () => sut.Populate(value);

            action.Should().Throw <BuildException>();
        }
        public void PopulateDoesNotAssignIgnoredProperty()
        {
            var buildHistory = new BuildHistory();
            var model        = new SlimModel();

            var processor          = Substitute.For <IBuildProcessor>();
            var buildConfiguration = Substitute.For <IBuildConfiguration>();
            var propertyResolver   = Substitute.For <IPropertyResolver>();
            var typeCapability     = Substitute.For <IBuildCapability>();
            var valueCapability    = Substitute.For <IBuildCapability>();

            typeCapability.AutoPopulate.Returns(true);
            typeCapability.SupportsCreate.Returns(true);
            typeCapability.SupportsPopulate.Returns(true);
            typeCapability.ImplementedByType.Returns(typeof(DummyTypeCreator));
            valueCapability.SupportsCreate.Returns(true);
            valueCapability.ImplementedByType.Returns(typeof(DummyTypeCreator));

            var sut = new DefaultExecuteStrategy(buildHistory, _buildLog, processor);

            processor.GetBuildCapability(sut, BuildRequirement.Populate,
                                         typeof(SlimModel))
            .Returns(typeCapability);
            buildConfiguration.PropertyResolver.Returns(propertyResolver);
            propertyResolver.GetOrderedProperties(buildConfiguration, typeof(SlimModel))
            .Returns(typeof(SlimModel).GetProperties());
            processor.GetBuildCapability(sut, BuildRequirement.Create,
                                         Arg.Is <PropertyInfo>(x => x.Name == nameof(SlimModel.Value)))
            .Returns(valueCapability);
            processor.GetBuildCapability(sut, BuildRequirement.Populate,
                                         typeof(Guid))
            .Returns(valueCapability);
            typeCapability.Populate(sut, model).Returns(model);
            propertyResolver.IsIgnored(
                Arg.Any <IBuildConfiguration>(),
                Arg.Any <object>(),
                Arg.Any <PropertyInfo>(),
                Arg.Any <object[]>()).Returns(true);

            sut.Initialize(buildConfiguration);

            var actual = (SlimModel)sut.Populate(model);

            actual.Value.Should().BeEmpty();

            typeCapability.DidNotReceive()
            .CreateProperty(sut, Arg.Is <PropertyInfo>(x => x.Name == nameof(SlimModel.Value)), null !);
        }
        public void PopulateReturnsInstanceWhenNoBuildActionCapabilityFound()
        {
            var buildHistory = new BuildHistory();
            var model        = new SlimModel();

            var processor          = Substitute.For <IBuildProcessor>();
            var buildConfiguration = Substitute.For <IBuildConfiguration>();

            var sut = new DefaultExecuteStrategy(buildHistory, _buildLog, processor);

            sut.Initialize(buildConfiguration);

            var actual = sut.Populate(model);

            actual.Should().Be(model);
        }
        public void PopulateAssignsPropertyValuesToExistingInstance()
        {
            var buildHistory = new BuildHistory();
            var model        = new SlimModel();
            var expected     = Guid.NewGuid();
            var properties   = typeof(SlimModel).GetProperties();
            var propertyInfo = properties.Single();

            var processor          = Substitute.For <IBuildProcessor>();
            var buildConfiguration = Substitute.For <IBuildConfiguration>();
            var propertyResolver   = Substitute.For <IPropertyResolver>();
            var typeCapability     = Substitute.For <IBuildCapability>();
            var valueCapability    = Substitute.For <IBuildCapability>();

            typeCapability.AutoPopulate.Returns(true);
            typeCapability.SupportsCreate.Returns(true);
            typeCapability.SupportsPopulate.Returns(true);
            typeCapability.ImplementedByType.Returns(typeof(DummyTypeCreator));
            valueCapability.SupportsCreate.Returns(true);
            valueCapability.ImplementedByType.Returns(typeof(DummyTypeCreator));

            var sut = new DefaultExecuteStrategy(buildHistory, _buildLog, processor);

            processor.GetBuildCapability(sut, BuildRequirement.Populate,
                                         typeof(SlimModel))
            .Returns(typeCapability);
            buildConfiguration.PropertyResolver.Returns(propertyResolver);
            propertyResolver.GetOrderedProperties(buildConfiguration, typeof(SlimModel))
            .Returns(properties);
            processor.GetBuildCapability(sut, BuildRequirement.Create, propertyInfo)
            .Returns(valueCapability);
            valueCapability.CreateProperty(sut, propertyInfo, Arg.Any <object?[]?>())
            .Returns(expected);
            processor.GetBuildCapability(sut, BuildRequirement.Populate,
                                         typeof(Guid))
            .Returns(valueCapability);
            typeCapability.Populate(sut, model).Returns(model);

            sut.Initialize(buildConfiguration);

            var actual = (SlimModel)sut.Populate(model);

            actual.Value.Should().Be(expected);
        }
        public void PopulateAsObjectAssignsPropertyValuesToExistingInstanceTest()
        {
            var staff = new List<Person>();
            var name = Guid.NewGuid().ToString();
            var address = Guid.NewGuid().ToString();
            var expected = new Company();
            var valueGenerators = new List<IValueGenerator>();
            var typeCreators = new List<ITypeCreator>();

            var buildStrategy = Substitute.For<IBuildStrategy>();
            var typeCreator = Substitute.For<ITypeCreator>();
            var valueGenerator = Substitute.For<IValueGenerator>();

            typeCreators.Add(typeCreator);
            valueGenerators.Add(valueGenerator);

            buildStrategy.TypeCreators.Returns(typeCreators.AsReadOnly());
            buildStrategy.ValueGenerators.Returns(valueGenerators.AsReadOnly());

            var target = new DefaultExecuteStrategy();

            target.Initialize(buildStrategy, buildStrategy.GetBuildLog());

            typeCreator.CanCreate(
                typeof(IEnumerable<Person>),
                "Staff",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            typeCreator.Create(
                typeof(IEnumerable<Person>),
                "Staff",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(staff);
            typeCreator.Populate(staff, target).Returns(staff);
            valueGenerator.IsSupported(
                typeof(string),
                "Name",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            valueGenerator.Generate(typeof(string), "Name", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(name);
            valueGenerator.IsSupported(
                typeof(string),
                "Address",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            valueGenerator.Generate(
                typeof(string),
                "Address",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(address);

            var actual = (Company)target.Populate(expected);

            actual.Should().BeSameAs(expected);
            actual.Name.Should().Be(name);
            actual.Address.Should().Be(address);
            actual.Staff.Should().BeSameAs(staff);
        }
        public void PopulateThrowsExceptionWhenNotInitializedTest()
        {
            var value = new Person();

            var target = new DefaultExecuteStrategy();

            Action action = () => target.Populate(value);

            action.ShouldThrow<InvalidOperationException>();
        }
        public void PopulateThrowsExceptionWithNullInstanceTest()
        {
            var target = new DefaultExecuteStrategy();

            Action action = () => target.Populate(null);

            action.ShouldThrow<ArgumentNullException>();
        }
        public void PopulateSkipsPropertiesMarkedWithIgnoreRuleWithTypeMatchesBaseClassTest()
        {
            var staff = new List<Person>();
            var name = Guid.NewGuid().ToString();
            var expected = new SpecificCompany();
            var ignoreRule = new IgnoreRule(typeof(Company), "Name");
            var valueGenerators = new List<IValueGenerator>();
            var typeCreators = new List<ITypeCreator>();
            var ignoreRules = new List<IgnoreRule>
            {
                ignoreRule
            };

            var buildStrategy = Substitute.For<IBuildStrategy>();
            var typeCreator = Substitute.For<ITypeCreator>();
            var valueGenerator = Substitute.For<IValueGenerator>();

            typeCreators.Add(typeCreator);
            valueGenerators.Add(valueGenerator);

            buildStrategy.TypeCreators.Returns(typeCreators.AsReadOnly());
            buildStrategy.ValueGenerators.Returns(valueGenerators.AsReadOnly());
            buildStrategy.IgnoreRules.Returns(ignoreRules.AsReadOnly());

            var target = new DefaultExecuteStrategy();

            target.Initialize(buildStrategy, buildStrategy.GetBuildLog());

            typeCreator.CanCreate(
                typeof(IEnumerable<Person>),
                "Staff",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            typeCreator.Create(
                typeof(IEnumerable<Person>),
                "Staff",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(staff);
            typeCreator.Populate(staff, target).Returns(staff);
            valueGenerator.IsSupported(
                typeof(string),
                Arg.Any<string>(),
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            valueGenerator.Generate(
                typeof(string),
                Arg.Any<string>(),
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(name);

            var actual = (SpecificCompany)target.Populate(expected);

            actual.Should().BeSameAs(expected);
            actual.Name.Should().BeNullOrEmpty();
            actual.Staff.Should().BeSameAs(staff);
        }
        public void PopulatePushesInstanceIntoBuildChainWhilePopulatingTest()
        {
            var instance = new SlimModel();
            var testPassed = false;

            var generator = Substitute.For<IValueGenerator>();
            var buildStrategy = Substitute.For<IBuildStrategy>();

            var target = new DefaultExecuteStrategy();

            target.Initialize(buildStrategy, buildStrategy.GetBuildLog());

            buildStrategy.CreationRules.Returns(new List<CreationRule>().AsReadOnly());
            buildStrategy.ValueGenerators.Returns(
                new List<IValueGenerator>
                {
                    generator
                }.AsReadOnly());
            generator.When(
                x =>
                    x.Generate(
                        typeof(Guid),
                        nameof(SlimModel.Value),
                        Arg.Is<LinkedList<object>>(y => y.Last.Value == instance))).Do(
                x =>
                {
                    target.BuildChain.Should().HaveCount(1);
                    target.BuildChain.Should().Contain(instance);
                    testPassed = true;
                });

            generator.IsSupported(
                typeof(Guid),
                nameof(SlimModel.Value),
                Arg.Is<LinkedList<object>>(x => x.Last.Value == instance)).Returns(true);

            target.Populate(instance);

            testPassed.Should().BeTrue();
        }
        public void PopulatePopulatesReadOnlyReferencePropertiesTest()
        {
            var configuration = Model.BuildStrategy;
            var buildLog = configuration.GetBuildLog();

            var target = new DefaultExecuteStrategy<ReadOnlyParent>();

            target.Initialize(configuration, buildLog);

            var actual = new ReadOnlyParent();

            actual = target.Populate(actual);

            actual.Company.Address.Should().NotBeNullOrWhiteSpace();
            actual.AssignablePeople.Should().NotBeEmpty();
            actual.People.Should().NotBeEmpty();
            actual.RestrictedPeople.Should().BeEmpty();
            actual.Unassigned.Should().BeNull();
        }
        public void PopulateOnlySetsPublicPropertiesTest()
        {
            var expected = new PropertyScopes();
            var value = Guid.NewGuid();
            var valueGenerators = new List<IValueGenerator>();

            var buildStrategy = Substitute.For<IBuildStrategy>();
            var valueGenerator = Substitute.For<IValueGenerator>();

            valueGenerators.Add(valueGenerator);

            buildStrategy.ValueGenerators.Returns(valueGenerators.AsReadOnly());

            var target = new DefaultExecuteStrategy();

            target.Initialize(buildStrategy, buildStrategy.GetBuildLog());

            valueGenerator.IsSupported(typeof(Guid), Arg.Any<string>(), Arg.Any<LinkedList<object>>()).Returns(true);
            valueGenerator.Generate(typeof(Guid), Arg.Any<string>(), Arg.Any<LinkedList<object>>()).Returns(value);

            var actual = (PropertyScopes)target.Populate(expected);

            actual.Should().BeSameAs(expected);
            actual.Public.Should().Be(value);
            actual.InternalSet.Should().BeEmpty();
            actual.ReadOnly.Should().BeEmpty();
            PropertyScopes.GlobalValue.Should().BeEmpty();
        }
        public void PopulateAssignsValueUsingDefaultExecuteOrderRulesTest()
        {
            var first = SimpleEnum.Seventh;
            var second = Environment.TickCount;
            var third = Guid.NewGuid().ToString();
            var fourth = new Person();
            var expected = new PopulateOrderItem();
            var valueGenerators = new List<IValueGenerator>();
            var typeCreators = new List<ITypeCreator>();
            var executeOrderRules = Model.BuildStrategy.ExecuteOrderRules;

            var buildStrategy = Substitute.For<IBuildStrategy>();
            var typeCreator = Substitute.For<ITypeCreator>();
            var valueGenerator = Substitute.For<IValueGenerator>();

            typeCreators.Add(typeCreator);
            valueGenerators.Add(valueGenerator);

            buildStrategy.TypeCreators.Returns(typeCreators.AsReadOnly());
            buildStrategy.ValueGenerators.Returns(valueGenerators.AsReadOnly());
            buildStrategy.ExecuteOrderRules.Returns(executeOrderRules);

            var target = new DefaultExecuteStrategy();

            target.Initialize(buildStrategy, buildStrategy.GetBuildLog());

            valueGenerator.IsSupported(
                typeof(SimpleEnum),
                "Z",
                Arg.Is<LinkedList<object>>(x => x.Last.Value == expected)).Returns(true);
            valueGenerator.Generate(typeof(SimpleEnum), "Z", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(first);
            valueGenerator.IsSupported(typeof(int), "Y", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(true);
            valueGenerator.Generate(typeof(int), "Y", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(second);
            valueGenerator.IsSupported(typeof(string), "X", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(true);
            valueGenerator.Generate(typeof(string), "X", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(third);
            typeCreator.CanCreate(typeof(Person), "W", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(true);
            typeCreator.Create(typeof(Person), "W", Arg.Is<LinkedList<object>>(x => x.Last.Value == expected))
                .Returns(fourth);
            typeCreator.Populate(fourth, target).Returns(fourth);

            var actual = (PopulateOrderItem)target.Populate(expected);

            actual.Should().BeSameAs(expected);
            actual.Z.Should().Be(first);
            actual.Y.Should().Be(second);
            actual.X.Should().Be(third);
            actual.W.Should().BeSameAs(fourth);
        }