Search code examples
wpftdddelegatecommandcanexecute

How to unit test CanExecuteChanged and RaisePropertyChanged


I am trying to practice strict TDD and have run into issue related to DelegateCommands and testing that CanExecute has been called.

These are my two test titles: "When I select an item from the list I should be able to add child items" "When no item is selected from the list I should not be able to add child items"

now the first test passes because CanAddChildItems is never called by my unit test, so I wrote the second test to ensure that CanAddChildItems is getting called. It is not even if I Put AddChildItems.RaiseCanExecuteChaned() into the setter of SelectedListItem.

Obviously the application does not behave as required without the AddChildItems.RaiseCanExecuteChaned() but I can't put that in if I don't have a test that really tests it!

So any ideas how I can confidently test this scenario?


Solution

  • Assumptions:

    Your ViewModel exposes properties and commands for the view to bind to.

    EnablesAddChildItemsIfAnItemHasBeenSelected()
    
       viewModel.AddChildItemsCommand.CanExecuteChanged += MarkNotificationReceived; // dummy handler in test fixture
    
       viewModel.SelectedItem = someItemVM;
    
       Assert.IsTrue(viewModel.AddChildItemsCommand.CanExecute(params))
       Assert.IsTrue(this.ReceivedCanExecuteChangedNotification) // flag in test fixture
    

    If you find yourself doing this often, you can create your own utility classes PropertyChangeListener / CanExecuteChangeListener and pass in your viewmodel and property/command name.

    DisablesAddChildItemsIfThereIsNoSelection
        viewModel.SelectedItem = someItemVM
        var addChildItemsCmd = viewModel.AddChildItemsCommand;
        var changeListener = new CanExecuteChangeListener(addChildItemsCmd);
    
        viewModel.SelectedItem = null
    
        Assert.IsFalse(addChilditemsCmd.CanExecute(params))
        Assert.IsTrue(changeListener.NotificationReceived)