【问题标题】:Why does my Command.CanExecute always return false in unit test?为什么我的 Command.CanExecute 在单元测试中总是返回 false?
【发布时间】:2011-04-01 09:11:31
【问题描述】:

我的粘贴命令在正常执行期间似乎可以工作,但在单元测试中,CanExecute 方法总是返回 false

代码:

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);
    }
}

单元测试:

[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);
    }
}

【问题讨论】:

  • 您是否尝试在ViewModel.CanPasteExecute 中设置断点?是否根本不调用它或忽略该值可能很重要。
  • @Florian:是的,断点没有被命中。
  • 应该RegisterCommandBinding(pasteBinding, typeof(LookupViewModel));实际上是RegisterCommandBinding(pasteBinding, typeof(ViewModel));吗?
  • @Florian:又一个错字!我很抱歉。看看我是多么依赖编译器来解决我的粗心大意。

标签: c# wpf unit-testing icommand


【解决方案1】:

我猜您在某个时候将您的 CommandBindings 属性绑定到 UI 控件,并且该命令是从 UI 触发的?

RoutedCommandsApplicationCommands.Paste 一样,依赖于在触发命令的父 UI 元素上方存在 CommandBinding。命令的CanExucute 请求从调用命令的控件开始(当前焦点或命令的目标),然后像RoutedEvent 一样向上冒泡,寻找匹配的CommandBinding。当它找到一个时,它会执行绑定中的CanExecute 委托以返回您要查找的值。

因为您的测试中没有 UI,也没有命令的目标,所以调用命令的 CanExecute 将根本找不到委托,因此将返回 false。

所以,如果没有 UI,我认为您的当前形式的测试不会工作。

(我现在要去测试我的理论 - 稍后会编辑!)

【讨论】:

  • 谢谢,期待。
  • 嗨菲尔 - 从我的测试看来我是正确的。您是否将 UI 中的某些内容绑定到视图的 CommandBindings 属性?
  • 是的,我愿意。我已经在我的 ViewModel 上公开了可以完成工作的公共方法,并且我在我的单元测试中调用了这些方法。看起来有点脏,但总比没有单元测试好。
  • 只是想知道你是否找到了一种更好的方法来测试这些不会破坏封装的方法@PhilGan
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多