Spot the bug … and avoid the bug with a unit test helper class

I have a class with the following code. This looks OK but isn’t…

 

    public class Lot : INotifyPropertyChanged
    {

        private string _actualHighestBidder;
        
       
        
        public string ActualHighestBidder
        {
            get
            {
                return _actualHighestBidder;
            }
            set
            {
                if (_actualHighestBidder.Equals(value) != true)
                {
                    _actualHighestBidder = value;
                    RaisePropertyChanged("ActualHighestBidder");
                }
            }
        }

     -- SNIP -- Implementation of INotifyPropertyChanged omitted

Spot the problem in the code above!!!

 

Scroll down

 

 

Scroll down

 

 

 

The private variable “_actualHighestBidder” is a string and is null.
Calling Equals on a null variable causes an annoying NullReferenceException.

 

 

There are 2 ways to solve this

1. Initialize your private backed field

        private string _actualHighestBidder = string.Empty;

2. Test for null

 public string ActualHighestBidder
        {
            get
            {
                return _actualHighestBidder;
            }
            set
            {
                if ((_actualHighestBidder == null || _actualHighestBidder.Equals(value) != true))
                {
                    _actualHighestBidder = value;
                    RaisePropertyChanged("ActualHighestBidder");
                }
            }
        }

I prefer the first method
but
how do we make sure we are not introducing this bugs in the future?

Note
This bug is very annoying, because we get this exception at runtime!

 

Idea!
image
Set all properties to some values with reflection

So that we can have a test like this

        [TestMethod()]
        public void LotProperties_SetAllProperties_NoException()
        {
            Lot target = new Lot();

            target.SetAllPublicProperties();
            target.GetAllPublicProperties();
            
            Assert.IsNotNull(target);
        }

 

My implementation of these 2 methods look like the below…

The method SetAllPublicProperties, sets all properties via Reflection
And the method GetAllPublicProperties does the same but tries to read the values!!

using System;
using System.Diagnostics;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Tests.Integration.Utils
{
    public static class ReflectionHelper
    {



        public static void SetAllPublicProperties(this object target)
        {
            Type targetType = target.GetType();

            foreach (MemberInfo memberInfo in targetType.GetProperties())
            {
                //Debug.WriteLine("memberInfo: " + memberInfo.ToString());

                PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                if (propertyInfo != null)
                {
                    //Debug.WriteLine("propertyInfo: field " + propertyInfo.ToString());

                    if (propertyInfo.CanWrite)
                    {
                        MethodInfo setMethod = propertyInfo.GetSetMethod();


                        if (propertyInfo.PropertyType == typeof(string))
                        {
                            setMethod.Invoke(target, new object[] { "String parameter" });

                        }
                        else if (propertyInfo.PropertyType == typeof(bool))
                        {
                            setMethod.Invoke(target, new object[] { true });
                        }

                        else if (propertyInfo.PropertyType == typeof(Single))
                        {
                            setMethod.Invoke(target, new object[] { 123 });
                        }
                        else if (propertyInfo.PropertyType == typeof(Single?))
                        {
                            setMethod.Invoke(target, new object[] { null });
                            setMethod.Invoke(target, new object[] { (Single?)123 });
                        }
                        else
                        {
                            Assert.Fail("Generic Poperty setter not implemented for type: " + propertyInfo.PropertyType);
                        }
                    }
                }
            }
        }



        public static void GetAllPublicProperties(this object target)
        {
            Type targetType = target.GetType();

            foreach (MemberInfo memberInfo in targetType.GetProperties()) //System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.
            {
                //Debug.WriteLine("memberInfo: " + memberInfo.ToString());

                PropertyInfo propertyInfo = memberInfo as PropertyInfo;
                if (propertyInfo != null)
                {
                    //Debug.WriteLine("propertyInfo: field " + propertyInfo.ToString());

                    if (propertyInfo.CanRead)
                    {
                        MethodInfo getMethod = propertyInfo.GetGetMethod();

                        object readValue = getMethod.Invoke(target, null);

                        Debug.WriteLine("Value from property: " + readValue);

                    }
                }
            }
        }
    }
}

 

Use it and extend it to all your needed types!

Latest Posts

Popular Posts