Sunday, August 4, 2013

Testing private methods/functions using VSTS unit test with c#

In case you are new to VSTS unit testing, you can read my article from codeproject.com:- 12 FAQ’s on VSTS unit testing.

Before you make an opinion about me and this article let me admit I am a strong opponent of unit testing private methods. For me a “UNIT” in unit testing means the “Class” as a whole. So if I test public methods of the class the private methods get tested as well.

It’s like should we test the wall or should we test individual bricks of the wall. Logically if the wall stands then the bricks are doing good as well.

But then there is a saying:-




So we have some other school of thought who think “UNIT” can be lines of code and methods. So they think that if you are testing private methods it’s ok and ethically right. And also many times you are in some weird situation like you are trying to zero on the method where the defect is ? , private testing seems to be a reasonable solution.

So with due respect to the second school of thought this blog will discuss how we can test private functions /method using VSTS test.

For example below is a simple “Maths” class which has an “Add” function. This “Add” function does not allow negative numbers. So to check if the number is negative there is a simple private function called as “IsNegative”. So how do we test “IsNegative”  through VSTS unit test framework?.

public class Maths
{
        public int Add(int num1, int num2)
        {
            if(IsNegative(num1) && IsNegative(num2))
            {
                throw new Exception("Number should not be negative");
            }
            return num1 + num2;
        }

        private bool IsNegative(int num)
        {
            if (num > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

In order to invoke private methods in VSTS unit test we have a class called as “privateobject”. Create the object of “PrivateObject” class and pass the class whose private method needs to be invoked. You can then use the “PrivateObject” object to invoke the private methods / functions as shown in the below code.

PrivateObject o = new PrivateObject(typeof(Maths));
bool b = Convert.ToBoolean(o.Invoke("IsNegative", -1));

FYI internally “PrivateObject” uses reflection to invoke the private members.

As said previously, unit testing private methods means there is seriously something wrong in the class design. This is also a sign that the class is overloaded with lot of responsibility and is not following SRP ( single responsibility responsible ). 

In this case the “Maths” class should only be doing arithmetic operations (Add, Subtract etc), but it is also loaded with responsibility of doing validation. So probably it’s a good idea to move the validation to a separate class called as “Validator” who will do the numeric checks and then use this class inside the “Maths” class.

You can then write test cases on the “Validator” class separately which is a cleaner approach than the previous approach of using “PrivateObject” and invoking them via reflection.

public class Validator
    {
        private bool IsNegative(int num)
        {
            if (num > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }

Below is a simple video I have created which shows how to use “PrivateObject” class to invoke the private methods.

No comments: