使用 CommandManager 时对 ICommand.CanExecute 进行单元测试

Posted

技术标签:

【中文标题】使用 CommandManager 时对 ICommand.CanExecute 进行单元测试【英文标题】:Unit testing ICommand.CanExecute when using CommandManager 【发布时间】:2019-05-01 11:19:50 【问题描述】:

(部分)我的 ICommand 实现是:

    public void RaiseCanExecuteChanged()
    
        CommandManager.InvalidateRequerySuggested();
    

    public event EventHandler CanExecuteChanged
    
        add
        
            CommandManager.RequerySuggested -= value;
            CommandManager.RequerySuggested += value;
        
        remove => CommandManager.RequerySuggested -= value;
    

调用 RaiseCanExecuteChanged() 时,这在 UI 中工作正常,但在单元测试中,我想知道 UI 是否已被通知它应该调用 CanExecute 方法。订阅 CanExecuteChanged 事件不起作用,因为使用 CommandManager 时不会触发此事件。 有谁知道如何测试 CommandManager.InvalidateRequerySuggested 是否被触发?

我也在考虑不使用 CommandManager 并将我的实现更改为:

    public void RaiseCanExecuteChanged()
    
        CanExecuteChanged?.Invoke(this, EventArgs.Empty);
    

    public event EventHandler CanExecuteChanged;

优点似乎是这只会触发对特定命令的 CanExecute 调用,而不是针对在 CommandManager 中注册的所有命令。有人可以确认我对 CommandManager 的理解是正确的吗?有谁知道这种“正常” CanExecuteChanged 事件的方法的缺点?

【问题讨论】:

如果所有依赖项都是可注入的,你可以编写单元测试,否则你不能。您的实现依赖于 CommandManager,它是不可注入,因此它是不可单元测试 【参考方案1】:

我个人更喜欢使用需要显式调用 CanExecuteChanged 的​​ ICommand 实现 - 我使用 MVVM Light RelayCommand。当您依赖 CommandManager 时,您永远不知道何时会调用 CanExecuteChanged - 可能是在每次击键或单击鼠标之后,这会变得非常低效。

关于我自己对 WPF 命令的看法,尤其是创建对其他属性的自动化 CanExecuteChanged 依赖项,请查看我最近的 blog post。

【讨论】:

以上是关于使用 CommandManager 时对 ICommand.CanExecute 进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章

通过CommandManager调用static查看命令记录

类库无法识别 CommandManager 类

BMW ICOM A2 Diagnostic & Programming For BMW ICOM A2+B+C 2016.07 Engineers Version

If BMW ICOM A2 clone with WiFi now

Free download 2016.6 BMW KSD ICOM A2 software

诊断瑞金中文数据库SQLiteDBs 4.13.31和ICOM Next 固件 V1.4.0