6

我目前正在开发我的一个项目,它是一个类似于 MSPaint 的 WPF 应用程序。但是,我不使用铅笔工具或类似的工具,而是使用对象(矩形、圆形、三角形等)进行绘画。我使用 Prism 和 MVVM 模型来实现可测试性和可维护性。

我现在遇到了一个问题。我有一个 CanvasView.xaml (顾名思义)我正在画的画布。我已经实现了自定义 Prism CommandBehaviors(即 MouseDownCommandBehavior),以提供一种将 ViewModel 的命令绑定到画布上的鼠标操作的方法。

基本设置如下所示:

public DelegateCommand<MouseEventArgs> MouseLeftButtonDownCommand { get; set; }

public CanvasViewModel(ICanvasView view, IEventAggregator eventAggregator) : base(view)
{
    m_View = view;
    m_EventAggregator = eventAggregator;
    m_EventAggregator.GetEvent<ToolboxSelectionChangedEvent>().Subscribe(OnToolboxSelectionChanged);


    MouseLeftButtonDownCommand = new DelegateCommand<MouseEventArgs>(OnMouseLeftButtonDown);
}

public void OnMouseLeftButtonDown(MouseEventArgs args)
{
    Point position = m_View.GetPosition(args);

    if(SelectedObject!=null){
        PaintObject po = SelectedObject.Clone();
        Canvas.SetLeft(po,position.X);
        Canvas.SetTop(po,position.Y);
        PaintObjects.Add(po);
    }
}

代码中没有的一些东西:

  • PaintObjects 是 View 上的 ItemsControl 绑定到的 PaintObject 对象的集合
  • PaintObject 是所有可用 PaintObject(矩形、圆形、三角形等)的基类。
  • SelectedObject(PaintObject 类型)由另一个 Prism 模块(工具箱)中的选择过程确定

问题是如何对 OnMouseLeftButtonDown 方法进行单元测试?问题是它严重依赖 MouseEventArgs,我真的不知道模拟/存根 MouseEventArgs 的好方法。

4

2 回答 2

8

I've been able to use the WPF Event Routing system to perform this type of unit testing with an attached property, and I assume that it will work the same with any other descendants of UIElement (Windows, etc.), because the .RaiseEvent() method in this code snippet is provided by the UIElement class:

 [TestMethod]
  public void ThingsShouldHappenWhenMouseIsClicked()
  {
     // ARRANGE
     var itemsControl = new ItemsControl ();
     var myDependencyMock = new Mock<IMyDependency>();
     // provide dependency to a dependency property
     MyAttachedProperty.SetDragDropHandler(itemsControl, myDependencyMock.Object);

     var leftClickEventArgs = new MouseButtonEventArgs(Mouse.PrimaryDevice, 0, MouseButton.Left)
     {
        RoutedEvent = UIElement.PreviewMouseLeftButtonDownEvent,
        Source = _itemsControl
     };

     // ACT
     itemsControl.RaiseEvent(leftClickEventArgs);

     // ASSERT
     myDependencyMock.Verify(x => x.TheThingHappened());
  }

I can't tell 100% for certain whether this will apply to the specific control types you've listed in your question, but hopefully this snippet will be helpful to someone.

于 2013-06-27T01:00:10.100 回答
3

使用附加层来消耗和发出鼠标事件。然后,您可以为您的单元测试存根/模拟该层。

于 2009-08-13T15:41:11.190 回答