This project is read-only.
1
Vote

Generic ValidationSpecification

description

I have a generic specification class which is not abstract and derives from Validates<T>. I use this class just for test purposes. The problem I have is, that your framework tries to instantiate my Mockup class in the background. This will always fail, because the GetType().IsGenericType == true . You are generally never able to instantiate generic types, therefore could you please ignore all generic types which derive from Validates<T> and are not abstract?
 
Kind regards,
 
Marinko

comments

TechnoAg wrote May 24, 2010 at 3:05 PM

Can you post your Mock Validates<T>, how you're configuring the ValidationCatalog (Scan?), and how you're calling your Mock Specification? We'll try and reproduce the issue and see what we can do.

marinko wrote May 27, 2010 at 2:49 PM

public class ValidationSpecMockup<TEntity> : ValidationSpecification<ValidationSpecMockup<TEntity>,TEntity>
{
    public ValidationSpecMockup() : base(true)
    {

    }

    public ActionOptionConditionBuilder<TEntity,TProperty> AddRule<TProperty>(Expression<Func<TEntity, TProperty>> expression, ValidationLevelType levelType = ValidationLevelType.Error)
    {
        return Check(expression);
    }

public abstract class ValidationSpecification<TSpecification, TEntity> : Validates<TEntity>, IValidationSpecification where TSpecification : ValidationSpecification<TSpecification, TEntity>, new()
{

    protected ValidationSpecification(bool isClientSideSpecification)
    {
        this.IsClientSideSpecification = isClientSideSpecification;
    }

    public bool IsClientSideSpecification { get; private set; }
}
Example Test:
    [TestMethod]
    public void DateFromToTest()
    {
        ValidationCatalog.Reset();
        var price = new Price() {DateFrom = DateTime.Now.AddDays(100), DateTo = DateTime.Now};
        var validationSpecMockup = new ValidationSpecMockup<Price>();
        validationSpecMockup.AddRule(p => p.DateTo)
            .If(p => p.DateFrom > p.DateTo).Required().GreaterThan(p => p.DateFrom);
        ValidationCatalog.SpecificationContainer.Add(validationSpecMockup);
        BrokenRules brokenRules = price.Validate();
        Assert.IsTrue(brokenRules.Count == 1);
    }
}
In my case I'm testing my own BrokenRules collection.

TechnoAg wrote May 27, 2010 at 4:16 PM

After looking at what you're trying to do, it looks very similar to our internal testing of the specifications and rules by creating a specification dynamically and validating an object. You can achieve the same functionality without all the base classes with this:

//Reset catalog to remove any other dynamically added specifications
ValidationCatalog.Reset();
//Dynamically build specification and add to Catalog
ValidationCatalog.AddSpecification<Price>( spec => spec.Check(p => p.DateTo).If(p => p.DateFrom > p.DateTo).Required().GreaterThan(p => p.DateFrom));

var price = new Price() {DateFrom = DateTime.Now.AddDays(100), DateTo = DateTime.Now};
var vn = ValidationCatalog.Validate(price);
Assert.IsTrue(vn.Errors.Count == 1);

There is another variation that we use on this same topic, We create an empty PriceSpec : Validates<Price> with no rules. Then you can do this in your test:

var priceSpec = new PriceSpec();
priceSpec .Check(p => p.DateTo).If(p => p.DateFrom > p.DateTo).Required().GreaterThan(p => p.DateFrom);
var vn = priceSpec.Validate(price);

We generally prefer the first approach since the tests includes the ValidationCatalog.

marinko wrote Jun 2, 2010 at 7:39 PM

Thanks a lot for your feedback. It's much nicer, than I expexted, but it would not work in my case.

BrokenRules brokenRules = price.Validate();

the validate method uses in background a filter to create a ValidationContext for client side validations from all existing Specification inside of ValidationCatalog

return ValidationCatalog<ValidationContextClient>.Validate(this);

ValidationContextClient contains code like

public ValidationContextClient()
    {

        foreach (var specification in ValidationCatalog.SpecificationContainer.GetAllSpecifications())
        {
            var validationSpecification = specification as IValidationSpecification;
            if(validationSpecification != null)
            {
                this.SpecificationContainer.Add(validationSpecification as Specification);
            }
        }            
    }
Why do you try to instantiate a generic ValidationSpecification? You will never be able to do that, because you have not TInstance Information. Just ignore generic classes during the scan process.

wrote Feb 14, 2013 at 3:51 AM