My Paste command seems to work during normal execution, but in unit test the CanExecute method always returns false.
Code:
public class ViewModel
{
public CommandBindingCollection CommandBindings { get; set; }
public ICommand PasteCommand { get; set; }
public ViewModel()
{
CommandBinding pasteBinding
= new CommandBinding(ApplicationCommands.Paste, Paste, CanPasteExecute);
RegisterCommandBinding(pasteBinding, typeof(ViewModel));
PasteCommand = (RoutedUICommand)pasteBinding.Command;
}
private void CanPasteExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
private void Paste(object sender, ExecutedRoutedEventArgs e)
{
// ...
}
private void RegisterCommandBinding(CommandBinding newCommandBinding, Type type)
{
if (CommandBindings == null)
CommandBindings = new CommandBindingCollection();
CommandManager.RegisterClassCommandBinding(type, newCommandBinding);
CommandBindings.Add(newCommandBinding);
}
}
Unit test:
[TestClass]
public class ViewModelTests
{
private ViewModel _viewModel;
[TestInitialize]
public void Initialise()
{
_viewModel = new ViewModel();
}
[TestMethod]
public void PasteTest()
{
// canExecute is always false somehow
bool canExecute = _viewModel.PasteCommand.CanExecute(null);
Assert.AreEqual<bool>(true, canExecute);
}
}
I’m guessing that you bind your
CommandBindingsproperty to a UI control at some point, and that the command is fired from the UI?RoutedCommandslikeApplicationCommands.Pasterely on there being aCommandBindingat a parent UI element, above that which the command is fired on. The command’sCanExucuterequest starts at the control on which the command is invoked (either the current focus or the command’s target), and bubbles upward like aRoutedEventlooking for a matchingCommandBinding. When it finds one, it executes theCanExecutedelegate from the binding to return the value you’re looking for.Because there’s no UI in your test, and no target for the command, calling the command’s
CanExecutewill simply not find a delegate and will thus return false.So, I don’t think your test in its current form would work without the UI being present.
(I’m going to go test my theory now – will edit later!)