Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

Testing Private Members in Visual Studio

4.00/5 (1 vote)
14 Apr 2010CC (Attr 3U)2 min read 18.5K  
How to test private members in Visual Studio

I’m currently working on a CommandBehaviour class to enable me to fire commands in response to arbitrary routed events on elements that don’t natively support commands, inspired by Sacha Barber’s post: WPF: Attached Commands.

Whilst trying to apply some unit tests to what I’m writing, I came across the age old problem of how to test things which are private by design. Under normal circumstances, I would probably have made them protected and written a TestableCommandBehaviour class in the test project that inherits from CommandBehaviour and exposes the protected members that I wanted to test.

However, in this particular instance, I’d already written the code, so I used the Create Unit Tests feature in Visual Studio to generate some unit tests for me to get me started. What I didn’t realise before was that when you do this, it creates a “Test Reference”, which provides you with a private accessor that you use to access the private code*.

Here’s a cut down version of the CommandBehaviour class:

C#
 1:  namespace DerekLakin.Libraries.Presentation
 2:  {
 3:      public class CommandBehaviour
 4:      {
 5:          public static readonly DependencyProperty CommandProperty =
 6:            DependencyProperty.RegisterAttached(
 7:              "Command",
 8:              typeof(ICommand),
 9:              typeof(CommandBehaviour),
10:              new UIPropertyMetadata(null));
11:
12:          public static readonly DependencyProperty CommandParameterProperty =
13:            DependencyProperty.RegisterAttached(
14:              "CommandParameter",
15:              typeof(object),
16:              typeof(CommandBehaviour),
17:              new UIPropertyMetadata(null));
18:
19:          public static readonly DependencyProperty EventNameProperty =
20:            DependencyProperty.RegisterAttached(
21:              "EventName",
22:              typeof(string),
23:              typeof(CommandBehaviour),
24:              new UIPropertyMetadata(string.Empty,
          new PropertyChangedCallback(EventNameChanged)));
25:
26:          private static readonly DependencyProperty CommandBehaviourProperty =
27:            DependencyProperty.RegisterAttached(
28:              "CommandBehaviour",
29:              typeof(CommandBehaviour),
30:              typeof(CommandBehaviour),
31:              new UIPropertyMetadata(null));
32:
33:          private readonly WeakReference sourceElement;
34:          private EventInfo eventInformation;
35:          private Delegate targetDelegate;
36:
37:          private CommandBehaviour()
38:          {
39:          }
40:
41:          private CommandBehaviour(DependencyObject source)
42:          {
43:              this.sourceElement = new WeakReference(source);
44:          }
45:          ...
46:      }
47:  }

A CommandBehaviour instance is created when the EventName attached property is set and the targetDelegate member is set when the relevant event has been hooked. In my unit test, I wanted to check that this member was actually being set and here’s how I did it using the accessor:

C#
 1:  [TestMethod]
 2:  [DeploymentItem("DerekLakin.Libraries.Presentation.dll")]
 3:  public void RemoveEventHandlerTest()
 4:  {
 5:      Grid source = new Grid();
 6:      source.SetValue(
 7:          CommandBehaviour.CommandProperty,
 8:          ApplicationCommands.Open);
 9:      source.SetValue(
10:          CommandBehaviour.EventNameProperty,
11:          "MouseLeftButtonUp");
12:      CommandBehaviour real = (CommandBehaviour)
13:          source.GetValue(
14:              CommandBehaviour_Accessor.CommandBehaviourProperty);
15:      CommandBehaviour_Accessor target =
16:          new CommandBehaviour_Accessor(
17:              new PrivateObject(real));
18:      Assert.IsNotNull(target.targetDelegate);
19:      target.RemoveEventHandler();
20:      Assert.IsNull(target.targetDelegate);
21:  }

First, I create a Grid instance and set the Command and EventName attached properties on it. Next, I get the CommandBehaviour instance from the Grid instance by using the accessor’s CommandBehaviourProperty (which is normally private). Then, I create a CommandBehaviour_Accessor instance that wraps the CommandBehaviour instance by using the PrivateObject class. Finally, I use regular Assert statements against the accessor to check the private members. Job done!

* For more information about testing private methods, see How to: Test a Private Method on the MSDN web site.

This work is licensed under a Creative Commons Attribution By license.

License

This article, along with any associated source code and files, is licensed under The Creative Commons Attribution 3.0 Unported License