diff --git a/src/Spring/Spring.Core/Validation/ExclusiveValidatorGroup.cs b/src/Spring/Spring.Core/Validation/ExclusiveValidatorGroup.cs
index fc5431f6..1711c3b0 100644
--- a/src/Spring/Spring.Core/Validation/ExclusiveValidatorGroup.cs
+++ b/src/Spring/Spring.Core/Validation/ExclusiveValidatorGroup.cs
@@ -82,7 +82,7 @@ namespace Spring.Validation
/// True if validation was successful, False otherwise.
protected override bool ValidateGroup(IDictionary contextParams, IValidationErrors errors, object validationContext)
{
- IValidationErrors tmpErrors = new ValidationErrors();
+ ValidationErrors tmpErrors = new ValidationErrors();
bool valid = false;
foreach (IValidator validator in Validators)
{
@@ -101,6 +101,11 @@ namespace Spring.Validation
}
}
+ if (!valid)
+ {
+ errors.MergeErrors(tmpErrors);
+ }
+
return valid;
}
diff --git a/test/Spring/Spring.Core.Tests/Validation/AnyValidatorGroupTests.cs b/test/Spring/Spring.Core.Tests/Validation/AnyValidatorGroupTests.cs
index 942af532..6f226980 100644
--- a/test/Spring/Spring.Core.Tests/Validation/AnyValidatorGroupTests.cs
+++ b/test/Spring/Spring.Core.Tests/Validation/AnyValidatorGroupTests.cs
@@ -21,7 +21,7 @@
#region Imports
using NUnit.Framework;
-
+using Rhino.Mocks;
using Spring.Expressions;
#endregion
@@ -35,6 +35,13 @@ namespace Spring.Validation
[TestFixture]
public sealed class AnyValidatorGroupTests
{
+ [Test]
+ public void DefaultsToFastValidate()
+ {
+ AnyValidatorGroup vg = new AnyValidatorGroup();
+ Assert.IsTrue(vg.FastValidate);
+ }
+
[Test]
public void WhenAllValidatorsReturnFalse()
{
@@ -72,9 +79,33 @@ namespace Spring.Validation
}
[Test]
- public void WhenSingleValidatorReturnsTrue()
+ public void WhenSingleValidatorReturnsTrueFastAndFastValidateIsTrue()
{
AnyValidatorGroup vg = new AnyValidatorGroup(Expression.Parse("true"));
+ vg.FastValidate = true;
+
+ WhenSingleValidatorReturnsTrue(vg);
+ // validators are called only until validation result is known
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[0]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[1]).WasCalled );
+ Assert.IsFalse( ((BaseTestValidator)vg.Validators[2]).WasCalled );
+ }
+
+ [Test]
+ public void WhenSingleValidatorReturnsTrueAndFastValidateIsFalse()
+ {
+ AnyValidatorGroup vg = new AnyValidatorGroup(Expression.Parse("true"));
+ vg.FastValidate = false;
+
+ WhenSingleValidatorReturnsTrue(vg);
+ // ALL validators are called
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[0]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[1]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[2]).WasCalled );
+ }
+
+ private static void WhenSingleValidatorReturnsTrue(AnyValidatorGroup vg)
+ {
vg.Validators.Add(new FalseValidator());
vg.Validators.Add(new TrueValidator());
vg.Validators.Add(new FalseValidator());
diff --git a/test/Spring/Spring.Core.Tests/Validation/CollectionValidatorTests.cs b/test/Spring/Spring.Core.Tests/Validation/CollectionValidatorTests.cs
index 23e96ac4..56a37a85 100644
--- a/test/Spring/Spring.Core.Tests/Validation/CollectionValidatorTests.cs
+++ b/test/Spring/Spring.Core.Tests/Validation/CollectionValidatorTests.cs
@@ -20,6 +20,13 @@ namespace Spring.Validation
[TestFixture]
public class CollectionValidatorTests
{
+ [Test]
+ public void DefaultsToFastValidateIsFalse()
+ {
+ CollectionValidator cg = new CollectionValidator();
+ Assert.IsFalse(cg.FastValidate);
+ }
+
[Test]
public void TestCollection()
{
diff --git a/test/Spring/Spring.Core.Tests/Validation/ExclusiveValidatorGroupTests.cs b/test/Spring/Spring.Core.Tests/Validation/ExclusiveValidatorGroupTests.cs
index cc1b7228..83419944 100644
--- a/test/Spring/Spring.Core.Tests/Validation/ExclusiveValidatorGroupTests.cs
+++ b/test/Spring/Spring.Core.Tests/Validation/ExclusiveValidatorGroupTests.cs
@@ -36,6 +36,13 @@ namespace Spring.Validation
[TestFixture]
public sealed class ExclusiveValidatorGroupTests
{
+ [Test]
+ public void DefaultsToFastValidate()
+ {
+ ExclusiveValidatorGroup evg = new ExclusiveValidatorGroup();
+ Assert.IsTrue(evg.FastValidate);
+ }
+
[Test]
public void WhenAllValidatorsReturnFalse()
{
@@ -52,7 +59,7 @@ namespace Spring.Validation
bool valid = vg.Validate(new object(), errors);
Assert.IsFalse(valid, "Validation should fail when all inner validators return false.");
- Assert.AreEqual(0, errors.GetErrors("errors").Count);
+ Assert.AreEqual(3, errors.GetErrors("errors").Count);
Assert.AreEqual(1, errors.GetErrors("exclusiveErrors").Count);
Assert.AreEqual(1, errors.GetErrors("existingErrors").Count);
}
@@ -97,6 +104,59 @@ namespace Spring.Validation
Assert.AreEqual(0, errors.GetErrors("errors").Count);
Assert.AreEqual(0, errors.GetErrors("exclusiveErrors").Count);
Assert.AreEqual(1, errors.GetErrors("existingErrors").Count);
+
+ // ALL validators are called
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[0]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[1]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[2]).WasCalled );
+ }
+
+ [Test]
+ public void WhenMultipleValidatorsReturnTrueAndFastValidate()
+ {
+ ExclusiveValidatorGroup vg = new ExclusiveValidatorGroup(Expression.Parse("true"));
+ vg.FastValidate = true;
+ IValidationErrors errors = new ValidationErrors();
+ WhenMultipleValidatorsReturnTrue(vg, errors);
+ // validators are called only until validation result is known
+ Assert.AreEqual(1, errors.GetErrors("errors").Count);
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[0]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[1]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[2]).WasCalled );
+ Assert.IsFalse( ((BaseTestValidator)vg.Validators[3]).WasCalled );
+ }
+
+ [Test]
+ public void WhenMultipleValidatorsReturnTrueAndNotFastValidate()
+ {
+ ExclusiveValidatorGroup vg = new ExclusiveValidatorGroup(Expression.Parse("true"));
+ vg.FastValidate = false;
+ IValidationErrors errors = new ValidationErrors();
+ WhenMultipleValidatorsReturnTrue(vg, errors);
+ // ALL validators are called
+ Assert.AreEqual(2, errors.GetErrors("errors").Count);
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[0]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[1]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[2]).WasCalled );
+ Assert.IsTrue( ((BaseTestValidator)vg.Validators[3]).WasCalled );
+ }
+
+ private void WhenMultipleValidatorsReturnTrue(ExclusiveValidatorGroup vg, IValidationErrors errors)
+ {
+ vg.Actions.Add(new ErrorMessageAction("exclusiveError", "exclusiveErrors"));
+
+ vg.Validators.Add(new FalseValidator());
+ vg.Validators.Add(new TrueValidator());
+ vg.Validators.Add(new TrueValidator());
+ vg.Validators.Add(new FalseValidator());
+
+ errors.AddError("existingErrors", new ErrorMessage("error", null));
+
+ bool valid = vg.Validate(new object(), errors);
+
+ Assert.IsFalse(valid, "Validation should not succeed when multiple inner validators return true.");
+ Assert.AreEqual(1, errors.GetErrors("exclusiveErrors").Count);
+ Assert.AreEqual(1, errors.GetErrors("existingErrors").Count);
}
[Test]
diff --git a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs
index 96aa4299..06ae2b2b 100644
--- a/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs
+++ b/test/Spring/Spring.Core.Tests/Validation/HelperClasses.cs
@@ -27,12 +27,30 @@ using Spring.Validation.Actions;
namespace Spring.Validation
{
+ public abstract class BaseTestValidator : BaseValidator
+ {
+ private bool _wasCalled;
+
+ public bool WasCalled
+ {
+ get { return _wasCalled; }
+ }
+
+ public override bool Validate(object validationContext, IDictionary contextParams, IValidationErrors errors)
+ {
+ _wasCalled = true;
+ return base.Validate (validationContext, contextParams, errors);
+ }
+
+ }
+
///
/// Helper classes for validation tests.
///
/// Aleksandar Seovic
- public class TrueValidator : BaseValidator
+ public class TrueValidator : BaseTestValidator
{
+
public TrueValidator()
{}
@@ -47,7 +65,7 @@ namespace Spring.Validation
}
}
- public class FalseValidator : BaseValidator
+ public class FalseValidator : BaseTestValidator
{
public FalseValidator()
{