Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Testing Private Members in Visual Studio

, 14 Apr 2010 CC (Attr 3U)
Rate this:
Please Sign up or sign in to vote.
Testing 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:

   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:

   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

Share

About the Author

Derek Lakin
Software Developer (Senior)
United Kingdom United Kingdom
No Biography provided

Comments and Discussions

 
GeneralGood point, interesting PinmemberEmile van Gerwen15-Jun-09 22:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 15 Apr 2010
Article Copyright 2009 by Derek Lakin
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid