You are here:   Blogs
REGISTER   |  LOGIN

Jenasys Design Blogs

MINIMISE

Business rules and unit testing

Jul 16

WRITTEN BY:
16/07/2010 9:24 AM  RssIcon

When migrating code from CSLA 3.0x to 3.8.x and upgrading from private member variables to CSLA PropertyInfo backing we discovered a very important lesson from our unit tests. Business rules, unit tests and RegisterProperty configuration all need to be in sync.

PropertyInfo code generated by CodeSmith CSLA templates r1814

Those familiar with the CSLA RegisterProperty method will note that no default value passed in, so it's going to default to Nothing in VB.
Private Shared ReadOnly _fullNameProperty As PropertyInfo(Of System.String) = RegisterProperty(Of System.String)(Function(p As User) p.FullName, String.Empty)
        
       Public Property FullName() As System.String
           Get
               Return GetProperty(_fullNameProperty)
           End Get
           Set (ByVal value As System.String)
               SetProperty(_fullNameProperty, value)
           End Set
       End Property

Is Unique CSLA Business Rule Example

It is common to have database fields with unique text at businesses (E.g. Application User name), so you have to have a matching CSLA Business Rule. You will notice that the code has had to be upgraded to include a IsNothing check for it to pass Nunit tests when migrating from Member Field backing in the CSLAContrib generated 3.0x CSLA to the CodeSmith CSLA 3.8.x code.
 
'''
''' Uses a generic Exists(criteria) method to determine if a database column(s) are unique before the record gets saved to the database.
''' This works in combination with database unique constraints.
'''
'''
''' We check for IsDirty or IsNew to ensure we are not running this IsUnique check when we use the DataPortal_Fetch to get the information from the database.  The database should manage constraints, so we should duplicate that effort.
''' TODO: Should look at making this a generic solution vs copying this to every business object.
'''
Private Shared Function IsUnique(Of T As BSO)(ByVal target As T, ByVal e As RuleArgs) As Boolean
    Dim result As Boolean
 
    If target.IsDirty OrElse target.IsNew Then
 
        '   Assumption: Field must be entered.
        '   IsNothing check inserted for CodeSmith CSLA templates, because the PropertyRegistration doesn't set a values, so it defaults to nothing or will cause Nunit tests to fail.
        If Not IsNothing(target.FullName) AndAlso target.FullName.Trim.Length > 0 Then
            Dim criteria As BSOCriteria = New UserCriteria
            '   Note:   You could add multiple field criteria if you had a Composite Unique Index. See http://msdn.microsoft.com/en-us/library/ms175132.aspx
            With criteria
                .FullName = target.FullName
                .IsUniqueExcludeIdentity = target.Identification
            End With
 
            '   Use the codesmith Exists method to check for existing values.
            If User.Exists(criteria) Then
                '   TODO: Waiting for the CodeSmith CSLA Templates to integrate PropertyInfo friendly names.
                e.Description = String.Format("{0} value of '{1}' already exists and cannot be used.", "User", target.FullName)
                result = False
            Else
                result = True
            End If
        Else
            '   Full name hasn't been entered, so it will be unique.
            result = True
        End If
    Else
        '   Assumption: the database can enforce unique columns ;)
        result = True
    End If
 
    Return result
End Function

Nunit code example.

Here is the simple unit test that found the issue. It looks fairly pointless, but in the end ensured I checked all the business rules migrated to the CodeSmith CSLA codebase. Nunit Support

'''
''' Ensure Full Name is unique
'''
'''
Sub UniqueName()
    Dim test As User
    test = User.NewUser
 
    With test
        ' We "know" that this name exists as we added it to the database for unit testing.
        .FullName = ""
    End With
 
    '   Should be a single broken rule
    Assert.AreEqual(1, test.BrokenRulesCollection.Count, "Name field must be unique")
End Sub

Conclusion

It is amazing what a simple unit test can teach you about your code and the assumptions that have been made for you from a code generator. It should remind developers of the importance of a unit tests role when designing CSLA Business Rules and ensuring that they are correct before your code gets released. If you want to benefit from CodeSmiths CSLA templates, remember that simple unit tests are a valuable way to finding implicit assumptions.

COPYRIGHT ©2010 Jenasys Design Pty Ltd


YOUR NAME:
Gravatar Preview
Your email:
(Optional) Email used only to show Gravatar.
Your website:
TITLE:
COMMENT:
SECURITY CODE
CAPTCHA image
ENTER THE CODE SHOWN ABOVE IN THE BOX BELOW
ADD COMMENT   CANCEL 

Disclaimer

MINIMISE
Any views expressed in these blogs or attachment/s are those of the individual author, and are not necessarily the views of Jenasys Design Pty Ltd. Please let us know if there are inappropriate or incorrect information displayed.

Search Blog entries

MINIMISE