There are various ways to test a Class member which is not public

  • By making the private members public of a class under test
    • Breaks the encapsulation principle
    • API is modified just for the sake of testing
  • By making the private members internal of a class under test and annotate the assembly with internalsVisibleTo attribute and you can read more about it at http://msdn.microsoft.com/en-us/library/0tke9fxk.aspx
    • Breaks the encapsulation principle
    • API is modified just for the sake of testing
  • Make the private members reachable through a public member of a class under test and test these public members
    • Breaks the encapsulation principle
    • API is modified just for the sake of testing
  • Use reflection to invoke the non public members of a class under test

Using reflection is abstracted in Visual Studio so we can use

  • PrivateObject to access non public Instance members of a class under test
  • PrivateType to access static members of a class under test

These classes are inside Microsoft.VisualStudio.TestTools.UnitTesting namespace. I have created code snippets in Visual Studio 2010.

PrivateObject:

PrivateObject class is used to access instance based members of  a class under test. The methods and properties of this class are displayed below

image

e.g. We have a BankAccount class that contains a private method i.e. VerifyAmount as displayed below

public class BankAccount
{
    //Private method to test
    private bool VerifyAmount(double amount)
    {
        return (amount <= 1000);
    }
 
}

In order to unit test VerifyAmount method using PrivateObject class the code is displayed below

[TestMethod()]        
public void VerifyAmountTest()
{
    //Using PrivateObject class
    PrivateObject privateHelperObject = new PrivateObject(typeof(BankAccount));                             
    double amount = 500F;
    bool expected = true;
    bool actual;
    actual = (bool)privateHelperObject.Invoke("VerifyAmount", amount);            
    Assert.AreEqual(expected, actual);            
}

 

PrivateType:

PrivateType class is used to access the static non public members of a class under test. The methods and properties of this class are displayed below

image

e.g. We have a BankAccount class that contains a private static method i.e. VerifyAmount as displayed below

public class BankAccount
{
    //Private static method under test
    private static bool VerifyAmount(double amount)
    {
        return (amount <= 2000);
    }
}

In order to unit test VerifyAmount method using PrivateType class the code is displayed below

[TestMethod()]        
public void VerifyAmountTest()
{
    PrivateType privateHelperType = new PrivateType(typeof(BankAccount));                             
    double amount = 1000F;
    bool expected = true;
    bool actual;
    actual = (bool)privateHelperType.InvokeStatic("VerifyAmount", amount);            
    Assert.AreEqual(expected, actual);            
}

 

In both the cases displayed above i.e. PrivateObject and PrivateType the method names are hardcoded. In order to avoid hard coding Visual Studio provides an option to create private accessor as displayed below where PrivateBanking is the name of the project.

image

Private Accessor automatically gets created when creating unit tests as displayed below

image

In the test project under Test References you can now see PrivateBanking.accessor as displayed below

image

The unit tests using the private accesser for class BankAccount as displayed below where BankAccount_Accessor is the class publicizes the BankAccount class and it derives from BaseShadow class.

//To test non public Instance member
[TestMethod()]
[DeploymentItem("PrivateBanking.dll")]
public void VerifyAmountTest1()
{
    BankAccount_Accessor target = new BankAccount_Accessor(); // TODO: Initialize to an appropriate value
    int amount = 10; // TODO: Initialize to an appropriate value
    bool expected = true; // TODO: Initialize to an appropriate value
    bool actual;
    actual = target.VerifyAmount(amount);
    Assert.AreEqual(expected, actual);            
}
 
//To test non public static member
[TestMethod()]
[DeploymentItem("PrivateBanking.dll")]
public void VerifyAmountTest()
{
    double amount = 10F; // TODO: Initialize to an appropriate value
    bool expected = true; // TODO: Initialize to an appropriate value
    bool actual;
    actual = BankAccount_Accessor.VerifyAmount(amount);
    Assert.AreEqual(expected, actual);           
}

As we are using the accessor now no hard coding is required for method names as displayed in code snippet above. The BankAccount_Accessor class is displayed below

image

The BaseShadow class is used by the publicize method to help test private types and is displayed below

image

This concludes the article on how to unit test non public members using Visual Studio 2010.