Tuesday, September 14, 2004 - Posts

The inner works of private method testing in VS Team System

While researching for a presentation of code quality tools in Visual Studio .NET 2005 Team System I discovered that you can create unit tests for private methods in your test fixtures. Since the target and the test fixture are two separate classes they do not have access to each others private members, still the Team System unit testing framework enables you to access these. As a curious cat, I had to investigate how this is accomplished.
The following snippet is taken form the Woodgrove Bank walkthrough project's BankAccount class:
1// private method:
2private accountType GetAccountType
3{
4 get
5 {
6 if (Balance > 15.00)
7 return accountType.Platinum;
8 else
9 return accountType.Gold;
10 }
11}
And this is the unit-test code generated by the Team System unit test generator:
1/// <summary>
2/// GetAccountTypeTest is a test case for GetAccountType
3/// </summary>
4 [TestMethod()]
5 public void GetAccountTypeTest()
6 {
7 // TODO: Initialize to an appropriate value
8 string customerName = null;
9 // TODO: Initialize to an appropriate value
10 double balance = 0;
11
12 BankAccountNS.BankAccount target = new BankAccountNS.BankAccount(customerName, balance);
13
14 // TODO: Assign to an appropriate value for the property
15 BankAccountNS.BankAccount.accountType val = BankAccountNS.BankAccount.accountType.Gold;
16
17 BankAccount.BankAccountAccessor accessor = new BankAccount.BankAccountAccessor(target);
18 Assert.AreEqual(val, accessor.GetAccountType);
19
20 Assert.Inconclusive("Verify the correctness of this test method.");
21 }
Take note of the highlighted line. Instead of creating an instance of the BankAccount class directly the test case uses a BankAccountAccessor class. This class is also used to access fields and methods. However this class is not a part of the project or is it?
While no class is shown in the solution explorer, you will find a source file called CodeGenAccessors.cs in the project directory. This is an auto generated file and it contains the various accessor classes for your target.
The following snippet shows the proxy for the private GetAccountType method.

1    public BankAccountNS.BankAccount.accountType GetAccountType {
2 get {
3 return ((BankAccountNS.BankAccount.accountType)(m_privateObject.GetProperty("GetAccountType")));
4 }
5 }
6

Still the generated accessor is still a separate class from the test target, so how does this work?
The answer is simple. The testing framework applies a little reflection magic beneath the covers. The m_privateObject field is an instance of Microsoft.VisualStudio.QualityTools.UnitTesting.Framework.PrivateObject which uses the Type’s InvokeMember method to invoke the get property in the above example.
To use this technique in your own code simply do this:
1public class Thief {
2 public static void Main()
3 {
4 Safe somebodyElsesSafe=new Safe();
5 Console.WriteLine((string)somebodyElsesSafe.GetType().InvokeMember("secret",BindingFlags.GetField|BindingFlags.Instance|
6BindingFlags.NonPublic,null,somebodyElsesSafe,null));
7 }
8}
9public class Safe {
10 private string secret="This is a secret lock inside a safe!";
11}

This is a cunning solution to a classic unit testing problem. And although extra code is included in your project while testing it is much more elegant than making private members public, which was the previous technique of choice, while testing.

Attention, Norwegian .NET bloggers!

At Microsoft’s partner kick-off in Oslo last Wednesday, I spoke with Petter Schatvet, who is the Norwegian developer tools product manager, about compiling a list Norwegian Microsoft centric blogs. The list is to be published at the Norwegian .NET User Group (NNUG) homepage and links to key blogs might also be included on the Norwegian MSDN site.
I know a few Norwegian bloggers, but there are probably many more out there. Therefore I call upon all Norwegian bloggers to submit a link to their blog either by commenting on this post or by mailing me.
Below is list of all Norwegian blogs on my roll.

Anders Norås

Yours truly!

http://andersnoras.info or http://dotnetjunkies.com/weblog/anoras

Andreas Brunvol

Microsoft Architecture Advisor

http://blogs.msdn.com/abrunvol

Andreas Eide

MVP, Regional Director and President of NNUG

http://weblogs.asp.net/andrease/

Einar Ingebritsen

Development manager In Notus Systems

http://blog.dolittle.com/

Janok

Information for Norwegian Microsoft Partner

http://weblogs.asp.net/janok/

Mads Nissen

An Objectware colleague

http://weblogs.asp.net/mnissen/

Morten Abrahamsen

Software Architect at Ibistic Technologies AS

http://blog.morty.info/

Roy Tore Gurskevik

Another Objectware colleague

http://dotnetjunkies.com/WebLog/rtgurskevik/