开发者

Why does my Command.CanExecute always return false in unit test?

开发者 https://www.devze.com 2023-02-21 15:06 出处:网络
My Paste command seems to work during normal execution, but in unit test the CanExecute method alway开发者_如何学运维s returns false.

My Paste command seems to work during normal execution, but in unit test the CanExecute method alway开发者_如何学运维s 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 CommandBindings property to a UI control at some point, and that the command is fired from the UI?

RoutedCommands like ApplicationCommands.Paste rely on there being a CommandBinding at a parent UI element, above that which the command is fired on. The command's CanExucute request starts at the control on which the command is invoked (either the current focus or the command's target), and bubbles upward like a RoutedEvent looking for a matching CommandBinding. When it finds one, it executes the CanExecute delegate 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 CanExecute will 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!)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号