我有一个类(为简单起见,我将其称为 MyCustomCommand),它基本上接受两个用于 Execute 和 CanExecute 的委托(delegate)。此类实现 ICommand。然后,这允许我在我的 View 模型中声明一个属性,我从 XAML 绑定(bind)到该属性。
问题是我遇到了一个场景,由于依赖于我的一个名为 ApplyChangesCommand 的命令,我需要模拟 View 模型。我不相信依赖性是一件坏事。这个时候比较有必要。
由于这种依赖性,我正在使用 Mock Setups 创建一个基本上“什么都不做”来规避依赖性的回调。
既然我已经模拟了 View 模型,那么任何实例属性现在当然都是空的。这包括我的命令。
简单的例子是:
private void _somethingToExecute;
public ICommand ApplyChangesCommand { get { return MyCustomCommand(_somethingToExecute, e=>true); }
有什么方法可以让我实际调用 ApplyChangesCommand 的 _somethingToExecute? Callbase 无法解决问题,我也想不出任何其他方法来做到这一点。
一种解决方法是公开“_somethingToExecute”并在我的测试中创建 ApplyChangesCommand,但我不喜欢。
感谢任何建议。
谢谢
最佳答案
好吧,既然我有更多时间来研究这个不匆忙的工作,我明白了这个问题。您应该做的是使用注入(inject)工厂来创建 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 命令进行单元测试所需要的全部内容。如果您想要测试行为是否符合您的预期(意思是,它执行传入的委托(delegate)并使用该委托(delegate)返回预期值),那么这就是验收测试的领域。
注意:我在测试示例中使用了 Moq 模拟框架语法。
就我个人而言,我不会将这样的委托(delegate)传递给 Command
。相反,我会注入(inject) Command
需要的任何内容,并在 Command
中包含所有逻辑,在那里它更容易进行单元测试,并且对 VM 的依赖性更宽松。
关于c# - 当 viewmodel 包含 ICommand 时使用 Mock 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18192027/