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!

4 comments:

Purohit D said...

.net is one of the most user friendly software development platforms. ASP.net development gives the way to develop complex web applications and web pages. Even most of the Business Intelligence software are being made on .net platforms with integrating ASP.net as an essential functional part.

Anonymous said...

very useful but alot of types missing!

Anonymous said...

Same idea that CrashTest.Net is using.

http://www.crashtestnet.de/

John Liu said...

3. String.IsNullOrEmpty( _actualHighestBidder )

Post a Comment

Latest Posts

Popular Posts