Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#4.0

How to test a class member that is not public using Visual Studio 2010

4.75/5 (4 votes)
23 Sep 2010CPOL2 min read 39.3K  
How to test a class member that is not public using Visual Studio 2010

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 here
    • 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:

C#
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:

C#
[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:

C#
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:

C#
[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 accessor for class BankAccount as displayed below where BankAccount_Accessor is the class publicises the BankAccount class and it derives from BaseShadow class.

C#
//To test non public Instance member
[TestMethod()]
[DeploymentItem("PrivateBanking.dll")]
public void VerifyAmountTest1()
{
	BankAccount_Accessor target = new BankAccount_Accessor(); 
	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 the 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.



License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)