我有一个类(为了简单起见,我将其称为MyCustomCommand),它基本上接受Execute和CanExecute的两个委托。这个类实现ICommand。这样,我就可以在视图模型中声明一个从XAML绑定到的属性。
问题是,我遇到了一个场景,由于我的一个名为ApplyChangesCommand的命令中存在依赖项,我需要模拟视图模型。我还不相信依赖是件坏事。在这一点上,这是相对必要的。
由于这个依赖关系,我使用Mock Setups创建了一个回调,它基本上"不做任何事情"来规避依赖关系。
既然我已经模拟了视图模型,那么任何实例属性现在都是空的。这包括我的命令。
简单的例子是:
private void _somethingToExecute;
public ICommand ApplyChangesCommand { get { return MyCustomCommand(_somethingToExecute, e=>true); }
使用Mock有什么方法可以真正调用ApplyChangesCommand的_somethingToExecute吗?呼叫基地没有切断它,我想不出任何其他方法来做到这一点。
一种解决方法是将"_somethingToExecute"公开,并在我的测试中创建ApplyChangesCommand,但我不喜欢。
如有任何建议,不胜感激。
感谢
好吧,现在我有更多的时间来研究这个问题,而不是在工作中仓促行事,我看到了问题。您应该使用一个注入的工厂来创建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-mocking框架语法。
就我个人而言,我不会把这样的代表交给Command
。相反,我会注入Command
需要的任何东西,并在Command
中拥有所有逻辑,在那里它更容易进行单元测试,并且对VM的依赖性更宽松。