当viewmodel包含ICommand时,使用Mock进行单元测试

时间:2013-08-12 16:26:24

标签: c# unit-testing mocking viewmodel icommand

我有一个类(为简单起见,我称之为MyCustomCommand),它基本上接受两个Execute和CanExecute的Delegates。该类实现ICommand。然后,这允许我在我的视图模型中声明一个属性,我将其绑定到XAML。

问题是我遇到了一个场景,我需要模拟视图模型,因为我的一个命令名为ApplyChangesCommand。我不相信依赖是一件坏事。在这一点上它是相对必要的。

由于这种依赖性,我正在使用模拟设置创建一个Callback,它基本上“无所事事”来规避依赖。

现在我已经模拟了视图模型,任何实例属性当然都是null。这包括我的命令。

简单的例子是:

private void _somethingToExecute;
public ICommand ApplyChangesCommand { get { return MyCustomCommand(_somethingToExecute, e=>true); }

Mock有什么方法可以实际调用ApplyChangesCommand的_somethingToExecute吗? Callbase没有削减它,我想不出任何其他方式来做它。

一种解决方法是将“_somethingToExecute”公开并在我的测试中创建ApplyChangesCommand,但我不是粉丝。

任何建议表示赞赏。

由于

1 个答案:

答案 0 :(得分:1)

好的,既然我已经有更多的时间来看待这个没有匆忙上班,我就看到了这个问题。你应该做的是使用注入工厂来创建ApplyChangesCommand。然后,对于VM的单元测试,您只需验证该命令是否返回工厂创建的命令。以下是一个例子:

public class MyViewModel
{
    private MyCustomCommandFactory _commandFactory;
    private void _somethingToExecute;

    public MyViewModel(MyCustomCommandFactory commandFactory)
    {
        _commandFactory = commandFactory;
    }

    public ICommand ApplyChangesCommand  
    { 
        get 
        { 
            return _commandFactory.Create(_somethingToExecute, e=>true);
        }
    }
}

这假设您每次调用get时都想要创建一个新命令(这似乎是您设置它的方式)。如果您只需要为VM的生命周期创建一个命令,显然您只需通过VM构造函数中的工厂创建命令。

要对此进行单元测试,您可以执行以下操作:

[Test]
public void ApplyChangesCommand_Always_ReturnsFactoryCreatedCommand
{
    Mock<ICommand> mockCreatedCustomCommand = new Mock<ICommand>();
    Mock<MyCustomCommandFactory> mockCommandFactory = new Mock<MyCustomCommandFactory>();
    mockCreatedCustomCommand.Setup(p => p.Create(It.IsAny<Action>(), e => true))
                            .Returns(mockCreatedCustomCommand.Object);
    Assert.That(systemUnderTest.ApplyChangesCommand, Is.SameAs(mockCreatedCustomCommand.Object));
}

(对于你的代表实际是什么,改变Action。)

这是您应该对VM的命令进行单元测试的全部内容。如果您想测试行为是您所期望的(意味着,它执行传入的委托并使用该委托返回预期值),那么这就是验收测试的领域。

注意:我在测试示例中使用了Moq模拟框架语法。

就个人而言,我不会将这样的代表传递给Command。我会注入Command所需的任何内容,并在Command内部拥有所有逻辑,在那里更容易进行单元测试,并且对VM有更宽松的依赖性。