我目前正在开发一个项目,它是一个类似 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);
}
}
代码中未出现的一些内容:
问题是如何对 OnMouseLeftButtonDown 方法进行单元测试?问题是它严重依赖 MouseEventArgs,而且我真的不知道模拟/存根 MouseEventArgs 的好方法。
我已经能够使用 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% 确定这是否适用于您在问题中列出的特定控件类型,但希望此代码片段对某人有所帮助。
使用附加层来消耗和发出鼠标事件。然后您可以为单元测试存根/模拟该层。
定义一个类如下。
public class EventArgsWrapper
{
private MouseEventArgs e;
public EventArgsWrapper(MouseEventArgs e)
{
this.e = e;
}
public virtual MouseButtonState LeftButton { get { return e.LeftButton; } }
public virtual Point GetPosition(IInputElement element) { return e.GetPosition(element); }
}
在代码中将 MouseEventArgs 或 MouseButtonEventArgs 替换为 EventArgsWrapper。然后您可以在单元测试中模拟虚拟方法。