【问题标题】:Should I unit test the methods or commands on a view model?我应该对视图模型上的方法或命令进行单元测试吗?
【发布时间】:2012-07-12 23:37:35
【问题描述】:

我刚看完Jason Dolinger's video on MVVM,我想了解一下如何正确设置和单元测试我的视图模型的 ICommand 属性。

考虑以下带有 FooBarCommand ICommandProperty 的 ViewModel 类。

public class ViewModel : IViewModel
{
    public ICommand FooBarCommand { get; private set; }

    public bool CanExectuteFooBar()
    {
        return true;
    }

    public void FooBar()
    {
        //Do some FooBarish stuff
    }
}

public interface IViewModel
{
    void FooBar();
    System.Windows.Input.ICommand FooBarCommand { get; }
}

public class FooBarCommand : ICommand
{
    private ViewModel vm;

    public FooBarCommand(ViewModel vm)
    {
        this.vm = vm;
    }
    public bool CanExecute(object parameter)
    {
        return vm.CanExectuteFooBar();
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        vm.FooBar();
    }
}

因此,如果我对 ViewModel 的 FooBar 功能进行单元测试,我可以通过调用 testVM.FooBar() 或通过调用 testVM.FooBarCommand.Execute() 来执行命令来运行 FooBar()。哪个是首选?我倾向于测试 FooBarCommand 属性,因为最终视图上的按钮被绑定到 FooBarCommand 属性而不是 FooBar() 方法。

此外,由于我的 View 将绑定到 IViewModel 而不是 ViewModel,我应该能够从 IViewModel 接口中省略 FooBar() 方法完全正确吗?

【问题讨论】:

  • 如果你想对你的视图模型进行单元测试,你应该用 IMessageboxService 替换 System.Windows.MessageBox.Show 否则你会遇到麻烦;)
  • 哦,是的,我知道我在制作示例时并没有考虑到这一点。我现在在问题中解决了它。
  • 从界面中删除 FooBar 方法是对的。该方法和 CanExecute 方法实际上可以是内部的。如果您开始测试方法与命令,这与测试类的私有实现与公共“接口”没有什么不同,因为视图模型的使用者仅使用命令。

标签: .net wpf mvvm viewmodel view-model-pattern


【解决方案1】:

为什么不使用 DelegateCommand 或 RelayCommand?如果你这样做,你就不必问这个问题,因为只有 Comand 本身是公共的 - canexecute 和 execute 方法是私有的。

我们只需要对公共内容进行单元测试。

ps:不要错过我对您问题的评论,直接在您的视图模型中使用 IMessageBoxService 而不是 MessageBox。

【讨论】:

    【解决方案2】:

    在某些情况下,测试命令可能是另一个测试夹具,因为命令背后有逻辑(启用禁用按钮)。如果你只在CanExecute 方法上返回true,那么对命令进行单元测试是没有用的,但是当你的禁用-启用按钮包含复杂的逻辑时,你应该在不同的夹具中测试它。

    注意(不同意则忽略):

    1. 尝试使用relay command,而不是将虚拟机传递到 命令,最小化循环引用始终是最佳实践。
    2. 永远不要将不可测试对象引用到 VM(视图 - 包括消息框、具有复杂依赖关系树的大型对象等)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-01
      • 2015-02-26
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多