Click here to Skip to main content
15,884,933 members
Articles / Programming Languages / C#

Generic Properties Validator C# Code

Rate me:
Please Sign up or sign in to vote.
4.86/5 (11 votes)
18 Feb 2015CPOL3 min read 18.9K   22   7
Generic properties validator C# code

Introduction

In your different type of tests (unit, integration, UI), you often need to verify almost all properties of an object. Usually, it’s too much work to write all asserts for all of them and add a meaningful exception message in case of failure. I will show you how to write a generic validator which can save you a lot of time.

How We Usually Assert Objects

Imagine that we have the following class.

C#
public class ObjectToAssert
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PoNumber { get; set; }
    public decimal Price { get; set; }
    public DateTime SkipDateTime { get; set; }
}

We can write code like the one below if we want to assert two instances of the class- the expected and the actual one. The first is defined in our test and the real one can be returned from our DB or some web service.

C#
ObjectToAssert expectedObject = new ObjectToAssert()
{
    FirstName = "Anton",
    PoNumber = "TestPONumber",
    LastName = "Angelov",
    Price = 12.3M,
    SkipDateTime = new DateTime(1989, 10, 28)
};

ObjectToAssert actualObject = new ObjectToAssert()
{
    FirstName = "AntonE",
    PoNumber = "TestPONumber",
    LastName = "Angelov",
    Price = 12.3M,
    SkipDateTime = new DateTime(1989, 10, 28)
};

Assert.AreEqual<string>(expectedObject.FirstName, _
    actualObject.FirstName, "The first name was not as expected.");
Assert.AreEqual<string>(expectedObject.LastName, _
    actualObject.LastName, "The last name was not as expected.");
Assert.AreEqual<string>(expectedObject.PoNumber, _
    actualObject.PoNumber, "The PO Number was not as expected.");
Assert.AreEqual<decimal>(expectedObject.Price, _
    actualObject.Price, "The price was not as expected.");
DateTimeAssert.Validate(
expectedObject.SkipDateTime,
actualObject.SkipDateTime,
DateTimeDeltaType.Days,
1);

You can see how much code we need to verify every single property.

Note: We use DateTimeAssert class, to verify the dates properties, which is my custom implementation for validation of DateTimes using Delta. You can find more information in my article “Assert DateTime the Right Way MSTest NUnit“.

How to Create Generic Properties Validator

You can use reflection in order to create a better reusable validator.

C#
public class PropertiesValidator<K, T> where T : new() where K : new()
{
    private static K instance;      
    public static K Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new K();
            }
            return instance;
        }
    }

    public void Validate(T expectedObject, T realObject, params string[] propertiesNotToCompare)
    {
        PropertyInfo [] properties = realObject.GetType().GetProperties();
        foreach ( PropertyInfo currentRealProperty in properties)
        {
            if (!propertiesNotToCompare.Contains(currentRealProperty.Name))
            {
                PropertyInfo currentExpectedProperty = 
                expectedObject.GetType().GetProperty(currentRealProperty.Name);
                string exceptionMessage =
                    string.Format( "The property {0} of class {1} 
                    was not as expected.", currentRealProperty.Name, 
            currentRealProperty.DeclaringType.Name);

                if (currentRealProperty.PropertyType != typeof( DateTime) 
                    && currentRealProperty.PropertyType != typeof (DateTime ?))
                {
                    Assert .AreEqual(currentExpectedProperty.GetValue(expectedObject, null), 
                    currentRealProperty.GetValue(realObject, null ), exceptionMessage);
                }
                else
                {
                        DateTimeAssert.Validate(
                        currentExpectedProperty.GetValue(expectedObject, null)  as DateTime?,
                        currentRealProperty.GetValue(realObject, null) as DateTime ?,
                        DateTimeDeltaType .Minutes,
                        5);
                }
            }
        }
    }
}

We use singleton pattern to create an instance of the object without the new keyword in the client code. For the job, we have a static variable from generic type K which will be the type of the validator that will derive from our base PropertiesValidator. The T type will be the type of the objects to be validated.

The Validate method accepts 3 parameters the expected object, the actual one and a params array of the names of the properties which should be skipped to be validated.

The core logic of the method is pretty simple. Reflection is used to obtain the properties of the objects. Next we iterate through all and validate them. If the Property type is DateTime , we use the previously mentioned DateTimeAssert class.

If you want to create a custom validator in order to add additional asserts or skip the validation of properties, just derive the base PropertiesValidator class.

C#
public class ObjectToAssertValidator : 
    PropertiesValidator<ObjectToAssertValidator, ObjectToAssert>
{
    public void Validate(ObjectToAssert expected, ObjectToAssert actual)
    {
        this.Validate(expected, actual, "FirstName");
    }
}

The previously six lines of asserts now can be replaced with a single line of code.

C#
ObjectToAssertValidator.Instance.Validate(expectedObject, actualObject);

So Far in the C# Series

1. Implement Copy Paste C# Code
2. MSBuild TCP IP Logger C# Code
3. Windows Registry Read Write C# Code
4. Change .config File at Runtime C# Code
5. Generic Properties Validator C# Code
6. Reduced AutoMapper- Auto-Map Objects 180% Faster
7. 7 New Cool Features in C# 6.0
8. Types Of Code Coverage- Examples In C#
9. MSTest Rerun Failed Tests Through MSTest.exe Wrapper Application
10. Hints For Arranging Usings in Visual Studio Efficiently
11. 19 Must-Know Visual Studio Keyboard Shortcuts – Part 1
12. 19 Must-Know Visual Studio Keyboard Shortcuts – Part 2
13. Specify Assembly References Based On Build Configuration in Visual Studio
14. Top 15 Underutilized Features of .NET
15. Top 15 Underutilized Features of .NET Part 2
16. Neat Tricks for Effortlessly Format Currency in C#
17. Assert DateTime the Right Way MSTest NUnit C# Code
18. Which Works Faster- Null Coalescing Operator or GetValueOrDefault or Conditional Operator
19. Specification-based Test Design Techniques for Enhancing Unit Tests
20. Get Property Names Using Lambda Expressions in C#
21. Top 9 Windows Event Log Tips Using C#

 

If you enjoy my publications, feel free to SUBSCRIBE
Also, hit these share buttons. Thank you!

Source Code

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Automate The Planet
Bulgaria Bulgaria
CTO and Co-founder of Automate The Planet Ltd, inventor of BELLATRIX Test Automation Framework, author of "Design Patterns for High-Quality Automated Tests: High-Quality Test Attributes and Best Practices" in C# and Java. Nowadays, he leads a team of passionate engineers helping companies succeed with their test automation. Additionally, he consults companies and leads automated testing trainings, writes books, and gives conference talks. You can find him on LinkedIn every day.

Comments and Discussions

 
QuestionHow to use this validator when testing web APIs? Pin
Member 1477996825-Jun-20 5:29
Member 1477996825-Jun-20 5:29 
QuestionFluentAssertions Pin
Cvetomir Todorov13-May-15 21:15
Cvetomir Todorov13-May-15 21:15 
AnswerRe: FluentAssertions Pin
Anton Angelov14-May-15 8:35
Anton Angelov14-May-15 8:35 
QuestionDateTimeAssert.Validate method Pin
sccain201221-Feb-15 20:34
sccain201221-Feb-15 20:34 
AnswerRe: DateTimeAssert.Validate method Pin
Anton Angelov21-Feb-15 22:14
Anton Angelov21-Feb-15 22:14 
GeneralRe: DateTimeAssert.Validate method Pin
sccain201222-Feb-15 6:13
sccain201222-Feb-15 6:13 
AnswerRe: DateTimeAssert.Validate method Pin
Anton Angelov22-Feb-15 6:53
Anton Angelov22-Feb-15 6:53 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.