依赖 MouseEventArgs 的单元测试功能?

发布于 2024-08-01 13:33:52 字数 1399 浏览 3 评论 0原文

我目前正在开发一个类似 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 是 PaintObject 对象的集合,视图上的 ItemsControl 绑定到
  • PaintObject 是所有可用 PaintObjects(矩形、圆形、三角形等)的基类
  • SelectedObject (PaintObject 类型)由另一个 Prism 模块(工具箱)中的选择过程确定。

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

I am currently working on a project of mine which is a MSPaint-like WPF application. However I don't paint with pencil tools or something similar but with objects (Rectangle, Circle, Triangle etc.). I use Prism and the MVVM model to achieve testability and maintainability.

I've now run into a problem. I have a CanvasView.xaml that's (as the name suggests) the canvas I am painting on. I have implemented custom Prism CommandBehaviors (ie. MouseDownCommandBehavior) to provide a way to bind the commands of the ViewModel to the mouse actions on the canvas.

The basic setup looks like this:

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);
    }
}

Some things not present in the code:

  • PaintObjects is a collection of PaintObject objects that a ItemsControl on the View binds to
  • PaintObject is the base class for all usable PaintObjects (Rectangle, Circle, Triangle etc.)
  • The SelectedObject (of type PaintObject) is determined by a selection process in another Prism module (Toolbox)

The question is how can I unit test the OnMouseLeftButtonDown method? The problem is that it heavily relies on MouseEventArgs and I don't really know a good way to mock/stub MouseEventArgs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

病女 2024-08-08 13:33:52

我已经能够使用 WPF 事件路由系统通过附加属性执行此类单元测试,并且我假设它与 UIElement 的任何其他后代(Windows 等)的工作方式相同,因为 .RaiseEvent此代码片段中的 () 方法由 UIElement 类提供:

 [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());
  }

我无法 100% 确定这是否适用于您在问题中列出的特定控件类型,但希望此片段对某人有所帮助。

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.

瀟灑尐姊 2024-08-08 13:33:52

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

Use an additional layer to consume and emit mouse events. Then you can stub/mock out that layer for your unit tests.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文