Unit testing functions based on MouseEventArgs?

I am currently working on my project, which is a WPF application similar to MSPaint. However, I do not draw with a pencil or something similar, but with objects (Rectangle, Circle, Triangle, etc.). I use Prism and the MVVM model to achieve testability and maintainability.

Now I have a problem. I have CanvasView.xaml, which (as the name suggests) is the canvas on which I draw. I applied custom Prism CommandBehaviors (i.e. MouseDownCommandBehavior) to provide a way to bind ViewModel commands to mouse actions on the canvas.

The basic setup is as follows:

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 missing from the code:

  • PaintObjects is a collection of PaintObjects that the ItemsControl in the view binds to
  • PaintObject is the base class for all PaintObjects used (Rectangle, Circle, Triangle, etc.).
  • The selected object (of type PaintObject) is determined by the selection process in another Prism module (Toolbox)

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

+4
source share
2 answers

Use an extra layer to consume and emit mouse events. You can then drown / ridicule this level for your unit tests.

+2
source

I was able to use the WPF event routing system to do 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 snippet The code 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 say 100% for sure whether this will apply to the specific types of management that you indicated in your question, but I hope this fragment will be useful to someone.

+5
source

All Articles