http://msdn2.microsoft.com/en-us/library/ms184807.aspx talks of how to test private methods when working with Unit Tests in Visual Studio 2008.  These steps are applicable to Smart Device Unit Testing as well. Let me spend some time discussing this.

The problem with testing private methods is that test assemblies cannot access private or internal methods of the code under test. How can this be worked around?

Private Accessors

In VS, private accessors are used to address this problem and call such restricted-access code.  The approach is to use reflection to invoke the non-public methods of the CUT (code under test) assembly. In VS 2005, this accessor code was part of the Test Project itself.  In Visual Studio 2008, however, there is a slight change in the design. The reflection based private accessor code now resides in a separate assembly called the Private Accessor Assembly.

The private accessor assembly gets generated automatically when you generate a unit test for a private method from the IDE. The accessor assembly’s name is generated as <CUTassembly>_accessor.dll. It is not included in the projects references directly. There is a text file with .accessor extension added to the Test project which contains the name of the Accessor assembly. For Smart Device test projects, this file will also include a line “Device” that defines that this is a smart device accessor assembly. A successful compilation of the test project would generate the Accessor assembly at <test project folder>\bin\Debug, which is then referenced by the test assembly.

Note: Desktop unit testing supports manually generating private accessors for an assembly from command-line using the publicize utility. While this should work for smart devices for most cases, this is an unsupported scenario for smart devices in Orcas.

Using Private Accessors

Let me take the same BankAccount class I used in my previous blog. Let’s say that the DepositMoney method was made private.

private void DepositMoney(float depositAmount)

{

this._currentBalance += depositAmount;

}

 

On generating unit test for this method from IDE, the following test method is created in the test project:

/// <summary>

///A test for DepositMoney

///</summary>

[TestMethod()]

public void DepositMoneyTest()

{

// TODO: Initialize to an appropriate value

PrivateObject param0 = null;

// TODO: Initialize to an appropriate value

 

BankAccount_Accessor target = new BankAccount_Accessor(param0);

float depositAmount = 0F; // TODO: Initialize to an appropriate value

target.DepositMoney(depositAmount);

Assert.Inconclusive("A method that does not return a value cannot be verified.");

}

The BankAccount_Accessor class is defined in the private accessor assembly and contains shadow implementation for DepositMoney, which internally invokes BankAccount.DepositMoney using reflection. After taking care of the TODO’s in the generated code, the test method will look like the one below. The steps for executing these tests are same as for regular smart device unit tests (described in my earlier blog).

/// <summary>

///A test for DepositMoney

///</summary>

[TestMethod()]

public void DepositMoneyTest()

{

BankAccount_Accessor target = new BankAccount_Accessor(10);

float depositAmount = 10;

target.DepositMoney(depositAmount);

Assert.AreEqual(20, target.CurrentBalance, "Error in depositing 10$");     

}

Testing private members in Smart Device Projects should thus, hopefully, be fairly straightforward.