1

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?

Damian
  • 1,543
  • 15
  • 22
  • I'm having trouble understanding your description of what your tests do. Are you using UI tests for this? Or are you directly exercising the view model? Maybe you should write out some pseudo-code that describes the setup, execution, and assertions for each test, and add that to the question. Or at least some code for your view model, showing the DelegateCommand, Execute, and CanExecute methods. – Merlyn Morgan-Graham Jul 20 '11 at 05:51
  • @Merlyn - it's a bit coupled with the WPF MVVM blend - A command represents an action. It does something (Execute), exposes when it can be called (CanExecute) and raises an event CanExecuteChanged (for instance to tell a Button that it should now requery to set its enabled Property). – Gishu Jul 20 '11 at 11:51
  • I know what DelegateCommand does :) I just meant include some code in your question, and was trying to be specific as to which code you should include. This medium block of text that references code with no actual *code* is hard to read. – Merlyn Morgan-Graham Jul 20 '11 at 17:15

1 Answers1

3

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)
Gishu
  • 134,492
  • 47
  • 225
  • 308