public void Validates_collection()
        {
            var validator      = new InlineValidator <Root>();
            var impl1Validator = new InlineValidator <FooImpl1>();
            var impl2Validator = new InlineValidator <FooImpl2>();

            impl1Validator.RuleFor(x => x.Name).NotNull();
            impl2Validator.RuleFor(x => x.Number).GreaterThan(0);

            validator.RuleForEach(x => x.Foos).SetInheritanceValidator(v => {
                v.Add(impl1Validator)
                .Add(impl2Validator);
            });

            var result = validator.Validate(new Root {
                Foos = { new FooImpl1() }
            });

            result.Errors.Count.ShouldEqual(1);
            result.Errors[0].PropertyName.ShouldEqual("Foos[0].Name");

            result = validator.Validate(new Root {
                Foos = { new FooImpl2() }
            });
            result.Errors.Count.ShouldEqual(1);
            result.Errors[0].PropertyName.ShouldEqual("Foos[0].Number");
        }
        public async Task When_async_condition_executed_for_each_instance_of_RuleForEach_condition_should_not_be_cached()
        {
            var person = new Person {
                Children = new List <Person> {
                    new Person {
                        Id = 1
                    },
                    new Person {
                        Id = 0
                    }
                }
            };

            var childValidator = new InlineValidator <Person>();
            int executions     = 0;

            childValidator.WhenAsync(async(a, ct) => {
                executions++;
                return(a.Id != 0);
            }, () => {
                childValidator.RuleFor(a => a.Id).Equal(1);
            });
            var personValidator = new InlineValidator <Person>();

            personValidator.RuleForEach(p => p.Children).SetValidator(childValidator);

            var validationResult = await personValidator.ValidateAsync(person);

            validationResult.IsValid.ShouldBeTrue();
            executions.ShouldEqual(2);
        }
        public void Can_define_nested_rules_for_collection()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders).ChildRules(order => {
                order.RuleFor(x => x.ProductName).NotNull();
                order.RuleFor(x => x.Amount).GreaterThan(0);
            });

            var result = validator.Validate(new Person {
                Orders = new List <Order> {
                    new Order {
                        ProductName = null, Amount = 10
                    },
                    new Order {
                        ProductName = "foo", Amount = 0
                    },
                    new Order {
                        ProductName = "foo", Amount = 10
                    }
                }
            });

            result.Errors.Count.ShouldEqual(2);
            result.Errors[0].PropertyName.ShouldEqual("Orders[0].ProductName");
            result.Errors[1].PropertyName.ShouldEqual("Orders[1].Amount");
        }
示例#4
0
        public void Rule_ForEach_display_name_should_match_RuleForEach_display_name()
        {
            var validator = new InlineValidator <Person>();

            // These 2 rule definitions should produce the same error message and property name.
            // https://github.com/FluentValidation/FluentValidation/issues/1231

            validator
            .RuleForEach(x => x.NickNames)
            .Must(x => false)
            .WithMessage("{PropertyName}");

            validator
            .RuleFor(x => x.NickNames)
            .ForEach(n => n.Must(x => false).WithMessage("{PropertyName}"));

            var result = validator.Validate(new Person()
            {
                NickNames = new[] { "foo" }
            });

            result.Errors[0].PropertyName.ShouldEqual("NickNames[0]");
            result.Errors[0].ErrorMessage.ShouldEqual("Nick Names");

            result.Errors[1].PropertyName.ShouldEqual("NickNames[0]");
            result.Errors[1].ErrorMessage.ShouldEqual("Nick Names");
        }
        public async Task RuleForEach_async_RunsTasksSynchronously()
        {
            var validator = new InlineValidator <Person>();
            var result    = new List <bool>();

            validator.RuleForEach(x => x.Children).MustAsync(async(person, token) =>
                                                             await ExclusiveDelay(1)
                                                             .ContinueWith(t => result.Add(t.Result), token)
                                                             .ContinueWith(t => true, token)
                                                             );

            await validator.ValidateAsync(new Person()
            {
                Children = new List <Person> {
                    new Person(), new Person()
                }
            });

            Assert.NotEmpty(result);
#if NET35
            AssertEx
#else
            Assert
#endif
            .All(result, Assert.True);
        }
		public void Nested_collection_for_null_property_should_not_throw_null_reference() {
			var validator = new InlineValidator<request>();
			validator.When(r => r.person != null, () => {
				validator.RuleForEach(x => x.person.NickNames).NotNull();
			});

			var result = validator.Validate(new request());
			result.Errors.Count.ShouldEqual(0);
		}
示例#7
0
        public void Nested_collection_for_null_property_should_not_throw_null_reference()
        {
            var validator = new InlineValidator <request>();

            validator.When(r => r.person != null, () => { validator.RuleForEach(x => x.person.NickNames).NotNull(); });

            var result = validator.Validate(new request());

            result.Errors.Count.ShouldEqual(0);
        }
示例#8
0
        public void ShouldHaveChildValidator_should_work_with_DependentRules()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleFor(x => x.Children)
            .NotNull().When(p => true)
            .DependentRules(() => {
                validator.RuleForEach(p => p.Children).SetValidator(p => new InlineValidator <Person>());
            });

            validator.ShouldHaveChildValidator(x => x.Children, typeof(InlineValidator <Person>));
        }
示例#9
0
        public async Task Can_access_colletion_index_async()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders).NotNull().WithMessage("{CollectionIndex}");
            var result = await validator.ValidateAsync(new Person { Orders = new List <Order>()
                                                                    {
                                                                        new Order(), null
                                                                    } });

            result.IsValid.ShouldBeFalse();
            result.Errors[0].ErrorMessage.ShouldEqual("1");
        }
示例#10
0
        public async Task Failing_condition_should_prevent_multiple_components_running_and_not_throw_async()
        {
            // https://github.com/FluentValidation/FluentValidation/issues/1698
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders)
            .MustAsync((o, ct) => Task.FromResult(o != null))
            .MustAsync((o, ct) => Task.FromResult(o != null))
            .When(x => x.Orders.Count > 0);

            var result = await validator.ValidateAsync(new Person());

            result.IsValid.ShouldBeTrue();
        }
示例#11
0
        public void Failing_condition_should_prevent_multiple_components_running_and_not_throw()
        {
            // https://github.com/FluentValidation/FluentValidation/issues/1698
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders)
            .NotNull()
            .NotNull()
            .When(x => x.Orders.Count > 0);

            var result = validator.Validate(new Person());

            result.IsValid.ShouldBeTrue();
        }
示例#12
0
        public void Can_use_cascade_with_RuleForEach()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.NickNames)
            .Cascade(CascadeMode.StopOnFirstFailure)
            .NotNull()
            .NotEqual("foo");

            var result = validator.Validate(new Person {
                NickNames = new string[] { null }
            });

            result.Errors.Count.ShouldEqual(1);
        }
示例#13
0
        public void Top_level_collection()
        {
            var v = new InlineValidator <IEnumerable <Order> >();

            v.RuleForEach(x => x).SetValidator(new OrderValidator());
            var orders = new List <Order> {
                new Order(),
                new Order()
            };

            var result = v.Validate(orders);

            result.Errors.Count.ShouldEqual(4);
            result.Errors[0].PropertyName.ShouldEqual("x[0].ProductName");
        }
        public void Does_not_throw_InvalidCastException_when_using_RuleForEach()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.NickNames)
            .Must(x => false)
            .WithMessage((parent, name) => "x");

            var result = validator.Validate(new Person()
            {
                NickNames = new[] { "What" }
            });

            result.Errors.Single().ErrorMessage.ShouldEqual("x");
        }
示例#15
0
        public void Nested_conditions_Rule_For_Each()
        {
            var validator = new InlineValidator <request>();

            validator.When(x => true, () => {
                validator.When(r => r.person?.NickNames?.Any() == true, () => {
                    validator.RuleForEach(x => x.person.NickNames)
                    .Must(nn => true)
                    .WithMessage("Failed RuleForEach");
                });
            });

            var result = validator.Validate(new request());

            result.Errors.Count.ShouldEqual(0);
        }
        public void Transforms_collection_element()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders)
            .Transform(order => order.Amount)
            .GreaterThan(0);

            var result = validator.Validate(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                }
            });

            result.Errors.Count.ShouldEqual(1);
        }
示例#17
0
        public void Can_use_indexer_in_string_message_inverse()
        {
            var validator      = new InlineValidator <Person>();
            var orderValidator = new InlineValidator <Order>();

            orderValidator.RuleFor(x => x.ProductName).Null();
            validator.RuleForEach(x => x.Orders).SetValidator(orderValidator);

            var model = new Person {
                Orders = new List <Order> {
                    new Order()
                }
            };
            var result = validator.TestValidate(model);

            result.ShouldNotHaveValidationErrorFor("Orders[0].ProductName");
        }
        public async Task Transforms_collection_element_async()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.Orders)
            .Transform(order => order.Amount)
            .MustAsync((amt, token) => Task.FromResult(amt > 0));

            var result = await validator.ValidateAsync(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                }
            });

            result.Errors.Count.ShouldEqual(1);
        }
        public void Should_work_with_top_level_collection_validator_and_overriden_name()
        {
            var personValidator = new InlineValidator <Person>();

            personValidator.RuleFor(x => x.Surname).NotNull();

            var validator = new InlineValidator <List <Person> >();

            validator.RuleForEach(x => x).SetValidator(personValidator).OverridePropertyName("test");


            var results = validator.Validate(new List <Person> {
                new Person(), new Person(), new Person {
                    Surname = "Bishop"
                }
            });

            results.Errors.Count.ShouldEqual(2);
            results.Errors[0].PropertyName.ShouldEqual("test[0].Surname");
        }
示例#20
0
        public void Uses_useful_error_message_when_used_on_non_property()
        {
            var validator = new InlineValidator <Person>();

            validator.RuleForEach(x => x.NickNames.AsEnumerable()).NotNull();

            bool thrown = false;

            try {
                validator.Validate(new Person {
                    NickNames = new string[] { null, null }
                });
            }
            catch (System.InvalidOperationException ex) {
                thrown = true;
                ex.Message.ShouldEqual("Could not infer property name for expression: x => x.NickNames.AsEnumerable(). Please explicitly specify a property name by calling OverridePropertyName as part of the rule chain. Eg: RuleForEach(x => x).NotNull().OverridePropertyName(\"MyProperty\")");
            }

            thrown.ShouldBeTrue();
        }
示例#21
0
        public void When_runs_outside_RuleForEach_loop()
        {
            // Shouldn't throw an exception if the condition is run outside the loop.
            var validator = new InlineValidator <Tuple <Person> >();

            validator.RuleForEach(x => x.Item1.Orders).Must(x => false)
            .When(x => x.Item1 != null);

            var result = validator.Validate(Tuple.Create((Person)null));

            result.IsValid.ShouldBeTrue();

            result = validator.Validate(Tuple.Create(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                }
            }));
            result.IsValid.ShouldBeFalse();
        }
示例#22
0
        public async Task Resets_state_correctly_between_rules_async()
        {
            var v = new InlineValidator <Person>();

            v.RuleForEach(x => x.NickNames).NotNull();
            v.RuleFor(x => x.Forename).NotNull();

            // The ValidationContext is reinitialized for each item in the collection
            // Specifically, the PropertyChain is reset and modified.
            // After the collection has been validated, the PropertyChain should be reset to its original value.
            // We can test this by checking the final output of the property names for subsequent rules after the RuleForEach.
            var result = await v.ValidateAsync(new Person()
            {
                NickNames = new[] { null, "Foo", null }, Forename = null
            });

            result.Errors.Count.ShouldEqual(3);
            result.Errors[0].PropertyName.ShouldEqual("NickNames[0]");
            result.Errors[1].PropertyName.ShouldEqual("NickNames[2]");
            result.Errors[2].PropertyName.ShouldEqual("Forename");
        }
示例#23
0
        public async Task When_runs_outside_RuleForEach_loop_async()
        {
            // Shouldn't throw an exception if the condition is run outside the loop.
            var validator = new InlineValidator <Tuple <Person> >();

            validator.RuleForEach(x => x.Item1.Orders)
            .MustAsync((x, c) => Task.FromResult(false))
            .When(x => x.Item1 != null);

            var result = await validator.ValidateAsync(Tuple.Create((Person)null));

            result.IsValid.ShouldBeTrue();

            result = await validator.ValidateAsync(Tuple.Create(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                }
            }));

            result.IsValid.ShouldBeFalse();
        }
示例#24
0
        public async Task Can_access_parent_index_async()
        {
            var personValidator = new InlineValidator <Person>();
            var orderValidator  = new InlineValidator <Order>();

            orderValidator.RuleFor(order => order.ProductName)
            .NotEmpty()
            .WithMessage("{CollectionIndex} must not be empty");

            // Two rules - one for each collection syntax.

            personValidator.RuleFor(x => x.Orders)
            .NotEmpty()
            .ForEach(order => {
                order.SetValidator(orderValidator);
            });

            personValidator.RuleForEach(x => x.Orders).SetValidator(orderValidator);

            var result = await personValidator.ValidateAsync(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                    {
                        ProductName = "foo"
                    },
                    new Order(),
                    new Order()
                    {
                        ProductName = "bar"
                    }
                }
            });

            result.IsValid.ShouldBeFalse();
            result.Errors[0].ErrorMessage.ShouldEqual("1 must not be empty");
            result.Errors[0].ErrorMessage.ShouldEqual("1 must not be empty");
        }
示例#25
0
        public void Shouldnt_break_with_hashcode_collision()
        {
            var v1 = new InlineValidator <Collision1>();
            var v2 = new InlineValidator <Collision2>();


            var v = new InlineValidator <CollisionBase>();

            v.When(x => x is Collision1, () => {
                v.RuleFor(x => ((Collision1)x).Name).NotNull();
            });
            v.When(x => x is Collision2, () => {
                v.RuleFor(x => ((Collision2)x).Name).NotNull();
            });

            // shouldn't throw an InvalidCastException.
            var containerValidator = new InlineValidator <List <CollisionBase> >();

            containerValidator.RuleForEach(x => x).SetValidator(v);
            containerValidator.Validate(new List <CollisionBase> {
                new Collision1(), new Collision2()
            });
        }
示例#26
0
        public async Task Shouldnt_break_with_hashcode_collision_async()
        {
            var v1 = new InlineValidator <Collision1>();
            var v2 = new InlineValidator <Collision2>();

            var v = new InlineValidator <CollisionBase>();

            v.WhenAsync((x, ct) => Task.FromResult(x is Collision1), () => {
                v.RuleFor(x => ((Collision1)x).Name).NotNull();
            });
            v.WhenAsync((x, ct) => Task.FromResult(x is Collision2), () => {
                v.RuleFor(x => ((Collision2)x).Name).NotNull();
            });

            var containerValidator = new InlineValidator <List <CollisionBase> >();

            containerValidator.RuleForEach(x => x).SetValidator(v);

            // shouldn't throw an InvalidCastException.
            await containerValidator.ValidateAsync(new List <CollisionBase> {
                new Collision1(), new Collision2()
            });
        }
        public async Task Validates_collection_async()
        {
            var validator      = new InlineValidator <Root>();
            var impl1Validator = new InlineValidator <FooImpl1>();
            var impl2Validator = new InlineValidator <FooImpl2>();

            impl1Validator.RuleFor(x => x.Name).MustAsync((s, token) => Task.FromResult(s != null));
            impl2Validator.RuleFor(x => x.Number).MustAsync((i, token) => Task.FromResult(i > 0));

            validator.RuleForEach(x => x.Foos).SetInheritanceValidator(v => {
                v.Add(impl1Validator)
                .Add(impl2Validator);
            });

            var result = await validator.ValidateAsync(new Root { Foos = { new FooImpl1() } });

            result.Errors.Count.ShouldEqual(1);
            result.Errors[0].PropertyName.ShouldEqual("Foos[0].Name");

            result = await validator.ValidateAsync(new Root { Foos = { new FooImpl2() } });

            result.Errors.Count.ShouldEqual(1);
            result.Errors[0].PropertyName.ShouldEqual("Foos[0].Number");
        }
        public void Creates_validator_using_context_from_property_value()
        {
            var personValidator = new InlineValidator <Person>();

            var normalOrderValidator = new InlineValidator <Order>();

            normalOrderValidator.RuleFor(x => x.Amount).GreaterThan(0);

            var freeOrderValidator = new InlineValidator <Order>();

            freeOrderValidator.RuleFor(x => x.Amount).Equal(0);

            personValidator.RuleForEach(x => x.Orders)
            .SetValidator((p, order) => order.ProductName == "FreeProduct" ? freeOrderValidator : normalOrderValidator);

            var result1 = personValidator.Validate(new Person()
            {
                Orders = new List <Order> {
                    new Order {
                        ProductName = "FreeProduct"
                    }
                }
            });

            result1.IsValid.ShouldBeTrue();

            var result2 = personValidator.Validate(new Person()
            {
                Orders = new List <Order> {
                    new Order()
                }
            });

            result2.IsValid.ShouldBeFalse();
            result2.Errors[0].ErrorCode.ShouldEqual("GreaterThanValidator");
        }