65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Visual Studio 中测试私有成员

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (1投票)

2009 年 6 月 12 日

CC (Attr 3U)

2分钟阅读

viewsIcon

18806

如何在 Visual Studio 中测试私有成员

我目前正在编写一个 CommandBehaviour 类,以便能够响应元素上任意路由事件触发命令,灵感来自 Sacha Barber 的文章:WPF: 附加命令

在尝试对正在编写的代码进行单元测试时,我遇到了一个老生常谈的问题:如何测试那些设计为私有的内容。在正常情况下,我可能会将它们设为受保护,并在测试项目中编写一个继承自 CommandBehaviour 并暴露我想要测试的 protected 成员的 TestableCommandBehaviour 类。

然而,在这种特定情况下,我已经编写了代码,所以我使用了 Visual Studio 中的 创建单元测试 功能来为我生成一些单元测试,以便开始。我之前没有意识到的是,当你这样做时,它会创建一个“测试引用”,它为你提供一个 *私有访问器*,你可以使用它来访问 private 代码。

以下是 CommandBehaviour 类的一个简化版本

   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:  }

当设置 EventName 附加属性时会创建一个 CommandBehaviour 实例,并且当相关事件被挂钩时,targetDelegate 成员会被设置。在我的单元测试中,我想检查该成员是否真的被设置,以下是我使用访问器的方法

   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:  }

首先,我创建一个 Grid 实例,并在其上设置 CommandEventName 附加属性。接下来,我使用访问器的 CommandBehaviourProperty(通常是 private)从 Grid 实例中获取 CommandBehaviour 实例。然后,我创建一个使用 PrivateObject 类包装 CommandBehaviour 实例的 CommandBehaviour_Accessor 实例。最后,我使用常规的 Assert 语句来检查 private 成员。完成了!

* 有关测试 private 方法的更多信息,请参阅 MSDN 网站上的 如何:测试私有方法

© . All rights reserved.