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 at https://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
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
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.
Private Accessor automatically gets created when creating unit tests as displayed below
In the test project under Test References you can now see PrivateBanking.accessor as displayed below
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
The BaseShadow class is used by the publicize method to help test private types and is displayed below
This concludes the article on how to unit test non public members using Visual Studio 2010.
del.icio.us Tags: visual Studio 2010,unit Test,Non public member
Comments
Anonymous
December 31, 2011
helpful topic..thanksAnonymous
February 17, 2012
can it be possible to do in visual studio 2008Anonymous
February 17, 2012
I've not tried in VS 2008. The use of Accessors has been deprecated in Visual Studio 2010 and might not be included in future versions of Visual Studio msdn.microsoft.com/.../bb385974.aspx Thanks.Anonymous
October 28, 2016
Thank you very much! Very useful tutorial, saved a lot of my time!Anonymous
January 09, 2017
Thx. Helps a lot 4 me