我正在努力实践严格的TDD,并且遇到了与delegatecommand和CanExecute已被调用的测试相关的问题。
这是我的两个测试标题:"当我从列表中选择一个项目时,我应该能够添加子项目"当列表中没有选择任何项时,我不应该能够添加子项"
现在第一个测试通过了,因为我的单元测试从来没有调用过CanAddChildItems,所以我编写了第二个测试来确保CanAddChildItems被调用。即使我把AddChildItems.RaiseCanExecuteChaned()放到SelectedListItem的setter中也不行。
显然,如果没有AddChildItems.RaiseCanExecuteChaned(),应用程序的行为就不符合要求,但如果我没有一个真正测试它的测试,我就不能把它放进去!
那么,有什么想法可以让我自信地测试这个场景吗?
假设:
你的ViewModel公开了视图绑定到的属性和命令。
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
如果你发现自己经常这样做,你可以创建你自己的实用程序类PropertyChangeListener/CanExecuteChangeListener,并传入你的视图模型和属性/命令名。
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)