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
1: namespace DerekLakin.Libraries.Presentation
3: publicclass CommandBehaviour
5: publicstaticreadonly DependencyProperty CommandProperty =
10: new UIPropertyMetadata(null));
12: publicstaticreadonly DependencyProperty CommandParameterProperty =
17: new UIPropertyMetadata(null));
19: publicstaticreadonly DependencyProperty EventNameProperty =
24: new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(EventNameChanged)));
26: privatestaticreadonly DependencyProperty CommandBehaviourProperty =
31: new UIPropertyMetadata(null));
33: privatereadonly WeakReference sourceElement;
34: private EventInfo eventInformation;
35: private Delegate targetDelegate;
37: private CommandBehaviour()
41: private CommandBehaviour(DependencyObject source)
43: this.sourceElement = new WeakReference(source);
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:
3: publicvoid RemoveEventHandlerTest()
5: Grid source = new Grid();
12: CommandBehaviour real = (CommandBehaviour)
15: CommandBehaviour_Accessor target =
16: new CommandBehaviour_Accessor(
17: new PrivateObject(real));
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](http://msdn.microsoft.com/en-us/library/ms184807.aspx "How to: Test a Private Method") on the MSDN web site.