ZeroSharp

Robert Anderson's ones and zeros

Testing the Property Signatures of DevExpress Validation Rules Using NUnit and LINQ

| Comments

One of the projects I work on uses the validation module of the eXpressApp Framework (XAF). Since the business logic is complex, there are many validation rules defined using the [RuleFromBoolProperty].

One of the recurring problems occurs when the signature of the associated property is incorrect. Consider the following:

1
2
3
4
5
6
7
8
9
10
11
[RuleFromBoolProperty("Invoice_IsAmountGreaterThanZero", 
  DefaultContexts.Save, 
  "Invoice amount must be greater than zero.", 
  UsedProperties = "Amount")]
public bool IsAmountGreaterThanZero
{
    get
    {
        return Amount > 0;
    }
}

Notice that the rule is declared public. This causes the getter to be executed when it is not required (see the note in the documentation). However another problem is that the default behaviour for public properties of XPObjects is to persist them to the datastore which means the application will attempt to create a new column called IsAmountGreaterThanZero.

Instead, either property should be declared protected or the property should also have the [NonPersistent] and [MemberDesignTimeVisibility(false)] attributes as well.

Consequently, I wrote the following unit test which will detect any properties which have the [RuleFromBoolProperty] attribute. This is not really a unit test, rather a sort of meta-test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[TestFixture]
public class ValidationRuleDeclarationMetaTests
{
 [Test]
  public void Test_RuleFromBoolPropertyDeclarations_ShouldBeProtectedVisibility()
  {
      var assemblies = new Assembly[] { typeof(MyObjectAssembly).Assembly };

      var invalidProperties = assemblies.SelectMany(a => a.GetTypes())
                                        .SelectMany(t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                                        .Where(p => p.GetCustomAttributes(typeof(RuleFromBoolPropertyAttribute), true)
                                                     .Any())
                                        .Select(p => String.Format("{0}.{1}", p.DeclaringType, p.Name))
                                        .Distinct();
  
      Assert.IsFalse(invalidProperties.Any(),
                     "There are 'public' properties with the [RuleFromBoolProperty] attribute. " +
                     "These should be 'protected' instead. " +
                     "The invalid properties are: " + String.Join(", ", invalidProperties));
  }
}  

Now the build will fail whenever a validation property signature is incorrect.

Comments