Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

October 29, 2009

Unit Testing: Exposing Private Members

Filed under: C#,Testing,VB.NET @ 6:19 pm

Visual Studio 2008 (Professional Edition and above) provides a really nice set of tools for development and execution of unit tests. It is, of  course, easy for your tests to access the public properties and methods of your classes. But what about those private members?

[To begin with an overview of unit testing, start here.]

[To expose internal (C#) or friend (VB) members, see this post.]

You may have properties or methods in your class defined  to be private. This post details how to test those methods using the unit testing features in Visual Studio.

NOTE: There are some testing philosophies that recommend you never test your private members; rather you test the public/internal/friend members and assume that those will provide coverage for all of your private members as well. Regardless of your point of view on this topic, this post provides the how-to so you can decide for yourself whether you want to or not.

Let’s say your Customer class has a CustomerId property that looks like this:

In C#:

private int? _CustomerId;
public int? CustomerId
{
    get { return _CustomerId; }
    private set
    {
        if (_CustomerId == null || !_CustomerId.Equals(value))
        {
            string propertyName = "CustomerId"; 
            if (!_CustomerId.Equals(value))
            {
                _CustomerId = value;
            }
        }
    }
}

In VB:

Private _CustomerId As Integer?
Public Property CustomerId() As Integer?
    Get
        Return _CustomerId
    End Get
    Private Set(ByVal value As Integer?)
        If _CustomerId Is Nothing OrElse _
                      Not _CustomerId.Equals(value) Then
            Dim propertyName As String = "CustomerId"
            If Not _CustomerId.Equals(value) Then
                _CustomerId = value
            End If
        End If
    End Set
End Property

Notice in both cases, the setter is private. The expectation is that the business object will set this value. However, you can you unit test it if you cannot set it?

The answer is PrivateObject.

PrivateObject is a class that allows test code to call class members that are not public. You PrivateObject to access private members of your class in your unit tests.

NOTE: You can also use PrivateObject for other non-public class members.

The following demonstrates how to use PrivateObject.

In C#:

/// <summary>
///A test for CustomerId
///</summary>
[TestMethod()]
public void CustomerIdTest()
{
    Customer target;
    int? expected;
    int? actual;

    // Null to Value
    target = new Customer();
    expected = 42;

    PrivateObject po = new PrivateObject(target);
    po.SetProperty("CustomerId", expected);
    actual = target.CustomerId;
    Assert.AreEqual(expected, actual, "Values are not equal");
}

In VB:

”'<summary>
”’A test for CustomerId
”'</summary>
<TestMethod()> _
Public Sub CustomerIdTest()
    Dim target As Customer
    Dim expected As Integer?
    Dim actual As Integer?

    ‘ Null to value
    target = New Customer
    expected = 42

    Dim po As PrivateObject = New PrivateObject(target)
    po.SetProperty("CustomerId", expected)
    actual = target.CustomerId
    Assert.AreEqual(expected, actual, "Values are not equal")
End Sub

NOTE: This is only part of the code you would need to fully test the CustomerId property.  Only one testing scenario was covered to instead focus on the PrivateObject syntax.

The code creates a new instance of PrivateObject, passing the instance of the class that has the private member you wish to access.

PrivateObject has methods such as GetProperty, SetProperty, GetField, SetField, and Invoke. These methods provide access to the private or other  non-public members of your class.

Use PrivateObject whenever you need to access a private member in your class from your unit testing code.

Enjoy!

6 Comments

  1.   CB — October 29, 2009 @ 7:46 pm    Reply

    Is there something — the [TestMethod()] attribute, perhaps — that restricts PrivateObject’s use?
    Or can it be used anywhere?

  2.   DeborahK — October 30, 2009 @ 10:09 am    Reply

    Hi CB –

    Thank you for visiting the blog.

    The PrivateObject is in the following namespace:

    Microsoft.VisualStudio.TestTools.UnitTesting

    And the description of the class is “Allows test code to call methods and properties on the code under test that would be inaccessible because they are not public. ”

    I don’t think it was meant to be used anywhere else.

    And maybe that is a good thing? If a class has private members, it seems that they should *not* be accessed by external code? (Testing being the only exception)?

  3.   Urs Enzler — October 30, 2009 @ 2:18 pm    Reply

    The only thing I miss here is a reason why I should call private members directly. If a private property or method cannot be tested by calling other public members or I have a need to test it independantly then the private member should be refactored out to a dedicated class. Otherwise, the Single Responsibility Principle is likely to be violated.

  4.   Alen Siljak — November 8, 2009 @ 8:13 pm    Reply

    Urs, the access to private methods/properties/fields is required if one does not want to change the public signature of the tested class but still wants to mock/stub the internal dependencies on other objects.
    Example: you want to test SomeClass that loads some data from the database using DataClass. You don’t want it to actually touch the database so you mock the DataClass to return a certain value say “3”. Since SomeClass does not expose DataClass in it’s public signature, the only way to cut the dependency on DataClass is to manipulate the internal variable holding the reference to DataClass and replace it with mock/stub object created outside of it.

  5.   Dennis "D.C." Dietrich — February 22, 2010 @ 9:31 pm    Reply

    I’m not a big fan of the interface of classes like PrivateObject or MbUnit’s Mirror. The resulting code on the caller side seems “unnatural”. Since C# 4.0 supports late-binding I’ve been experimenting with runtime code generation to provide wrappers on the fly. While that doesn’t get rid of the late-bound aspect of calling non-public members the code at least looks like it would for public members. I’ve published a hopefully stable version on my blog (would consider it somewhere between a late Alpha and a very early Beta) – general feedback and bug reports are most welcome.
    http://blogs.msdn.com/ddietric/archive/2010/01/24/d-c-and-the-wrapper-factory.aspx

  6.   Salomon MOYAL BLOCH Zurich, ch — January 21, 2011 @ 6:05 am    Reply

    It is an excellent Post for people how want to get a rid of the old method generating an accessor wrap-up layer.
    Now to my query:

    AutoResetEvent _semaphoreSendMsgContentionTimerExpired;

    private List _messageReceived;
    private int _frameNumberReceived;

    My private member is a generic whta should I use in the PrivateObject Method Invoke to get it to be tested within the UnitTest Project.

    TY

    Sincerely

    Salomon

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2023 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs