Click here to Skip to main content
15,885,720 members
Articles / Programming Languages / C# 4.0

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

Rate me:
Please Sign up or sign in to vote.
4.75/5 (4 votes)
23 Sep 2010CPOL2 min read 38.7K   11   4
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.



This article was originally posted at http://www.atulverma.com/feeds/posts/default

License

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


Written By
Software Developer (Senior)
India India
Atul works at Microsoft as a .NET consultant. As a consultant his job is to design, develop and deploy enterprise level secure and scalable solutions using Microsoft Technologies.

His technical expertise include .NET Framework(4.0, 3.5, 3.0), WPF, WCF, SharePoint 2010, ASP.net, AJAX, Web Services, Enterprise Applications, SQL Server 2008, Open Xml, MS Word Automation.

Follow him on twitter @verma_atul

He blogs at
http://www.atulverma.com
http://blogs.msdn.com/b/atverma

Comments and Discussions

 
QuestionIEnumerable return value [modified] Pin
Lars K16-Jun-11 6:17
Lars K16-Jun-11 6:17 
GeneralMy vote of 5 Pin
jim lahey12-Nov-10 1:44
jim lahey12-Nov-10 1:44 
GeneralRe: My vote of 5 Pin
atverma16-Nov-10 15:50
atverma16-Nov-10 15:50 
GeneralNice! Pin
Your Display Name Here5-Nov-10 4:30
Your Display Name Here5-Nov-10 4:30 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.