Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

How to Unit Test Private Methods in MS Test

DZone's Guide to

How to Unit Test Private Methods in MS Test

Should you test private methods in MS Test, and if so, how do you perform them? Here is a step-by-step guide.

· DevOps Zone
Free Resource

Learn more about how CareerBuilder was able to resolve customer issues 5x faster by using Scalyr, the fastest log management tool on the market. 

This article originally appeared on the Infragistics Blog by Dhananjay Kumar

Before we show how a private method can be unit tested using the MS Test, let us discuss whether it is a good idea to test a private method or not.  Often I have seen there are two schools of thought:

1.       Private methods should be tested.

2.       Private methods should not be tested.

To put these things in perspective, let us consider a system under test (SUT) Salary class as shown in the listing below.


namespace Calculator
{
    public class Salary
    {
        public int CalculateSal(int bs, int nwd)
        {
             int ts ;
             if(isValidNwd(nwd))
             {
                 ts= bs*nwd;
             }
             else
             {
                 ts = 1000;
             }
             return ts;
        }
        private bool isValidNwd(int nwd)
        {
            if (nwd > 8)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
    }
}


A system under a test Salary class has two functions:

1.       The CalculateSal method is a public method and it takes two parameters to calculate the salary.

2.       The isValidwd method is a private method and it takes one parameter. This function returns true if the number of working days are more than 8, or else it returns false.

3.       The CalculateSal method first checks whether the number of working days is valid or not using the private method isValidWd.

4.       If the number of working days is valid, then salary is calculated by the multiplication of basic salary and the number of working days, or else it is fixed at $1000.

 

Now we have a system under test Salary class with two functions.

One opinion is that the private method should not be unit tested separately. This is because the private method is used inside the public method and when we test the behavior of the public method, the behavior of the private method also gets tested.

Another opinion is that the private method must be unit tested for its own behavior in isolation with the other public or private methods. Before we go ahead and see how to test a private method, let us give some thought on whether there is another possible way to work around this.

 

Violating Single Responsibility Principle

Currently, the system under test Salary class is violating the Single Responsibility Principle because it has two responsibilities:

  1. To calculate the salary (public method).

  2. To validate the number of working days (private method).

 

We can’t be sure of good code coverage of SUT Salary class unless we test the validate working days behavior of the class, and is private by design. A good option could be this: while creating the Salary class, we can spilt the responsibilities in two separate classes with public methods to calculate the salary and validate working days. We can then write unit tests for public methods of both classes. Let’s see how to do that:

 

Writing Unit Test for Private methods

If you’re of the opinion that a private method in the SUT class should be tested, then you have two options:

1.       Use Refactoring – but this is bit complex.

2.       Use VSTS PrivateObject class - this is simple!

 










Let’s see how we can use a PrivateObject class to unit test a private method. To use a private object class you need to:

1.       Add a reference of Microsoft.VisualStudio.QualityTools.UnitTestFramework in the test project. If you have created project by selecting unit test project templet then this reference would be added by default in the project.

2.       Add a namespace Microsoft.VisualStudio.TestTools.UnitTesting.

The constructor of PrivateObjectClass takes the type as the parameter, so here you’ll need to pass type of the SUT Salary class and then on the object of PrivateObjectClass call the invoke method to invoke the private method.

We can test the private method isValidNwd as shown in the listing below:

 

 [TestMethod]
        public void ReturnTrueForValidWorkingDays()
        {
            PrivateObject objToTestPrivateMethod = new PrivateObject(typeof(Salary));
            bool result = Convert.ToBoolean(objToTestPrivateMethod.Invoke("isValidNwd", 6));
            Assert.AreEqual(result, true);
        }

 

Essentially, we are performing the following tasks:

  • Creating an object of PrivateObject class.

  • Passing a type of Salary class as an input parameter in the constructor.

  • Using the invoke method to execute the private method of the SUT Salary class.

  • Passing two parameters in the invoke method: the first parameter is the name of the private method and the second parameter is the argument which will be passed to the private method while executing.

And that’s how we can unit test a private method!

Conclusion

In this post we learnt about:

  • Whether to test a private method or not.

  • How to test the private method using the PrivateObject class.

I hope this post is useful for you - thanks for reading. Happy coding!

Find out more about how Scalyr built a proprietary database that does not use text indexing for their log management tool, allowing customers to search 1TB of data in under a second. 

Topics:
devops ,unit testing ,ms test manager ,microsoft

Published at DZone with permission of Josh Anderson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}