2009-08-13 6 views
4

Je travaille actuellement sur un de mes projets qui est une application WPF semblable à MSPaint. Cependant je ne peins pas avec des outils au crayon ou quelque chose de similaire mais avec des objets (Rectangle, Cercle, Triangle etc.). J'utilise Prism et le modèle MVVM pour obtenir la testabilité et la maintenabilité.Fonctions de test unitaire reposant sur MouseEventArgs?

J'ai maintenant rencontré un problème. J'ai un CanvasView.xaml qui est (comme son nom l'indique) la toile sur laquelle je peins. J'ai implémenté Prism CommandBehaviors personnalisé (c'est-à-dire MouseDownCommandBehavior) pour fournir un moyen de lier les commandes du ViewModel aux actions de la souris sur le canevas.

La configuration de base ressemble à ceci:

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

Certaines choses ne sont pas présentes dans le code:

  • PaintObjects est une collection d'objets PaintObject que ItemsControl sur la vue se lie à
  • PaintObject est la classe de base pour tous les objets PaintObjects utilisables (rectangle, cercle, triangle, etc.)
  • L'objet SelectedObject (de type PaintObject) est déterminé b y un processus de sélection dans un autre module Prism (Toolbox)

La question est de savoir comment tester la méthode OnMouseLeftButtonDown. Le problème est qu'il repose lourdement sur MouseEventArgs et je ne connais pas vraiment un bon moyen de mock/stub MouseEventArgs.

Répondre

2

Utilisez une couche supplémentaire pour consommer et émettre des événements de souris. Ensuite, vous pouvez copier/masquer cette couche pour vos tests unitaires.

+0

Pourriez-vous donner un exemple pour cela? – chrischu

5

J'ai pu utiliser le système de routage d'événements WPF pour effectuer ce type de test unitaire avec une propriété attachée, et je suppose qu'il fonctionnera de la même manière avec tous les autres descendants d'UIElement (Windows, etc.), parce que la méthode .RaiseEvent() dans cet extrait de code est fourni par la classe 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()); 
    } 

Je ne peux pas dire à 100% pour certains si cela s'appliquera aux types spécifiques de contrôle que vous avez énumérés dans votre question , mais j'espère que cet extrait sera utile à quelqu'un.