C# 如何使ViewModel中的InteractionRequest可测试?
我正在.NET4.0上为WPF使用PRISM和autofac,我想开发一个可测试的ViewModels。对于测试,我们使用nUnit和moq进行模拟 所以我有一门课:C# 如何使ViewModel中的InteractionRequest可测试?,c#,wpf,unit-testing,moq,C#,Wpf,Unit Testing,Moq,我正在.NET4.0上为WPF使用PRISM和autofac,我想开发一个可测试的ViewModels。对于测试,我们使用nUnit和moq进行模拟 所以我有一门课: public class BackupViewModel : InteractionRequestNotificationObject { private readonly DelegateCommand backupCommand; private readonly IBackupCommandSe
public class BackupViewModel : InteractionRequestNotificationObject
{
private readonly DelegateCommand backupCommand;
private readonly IBackupCommandService commandService;
private readonly InteractionRequest<SaveBrowserDialogViewModel> saveDialogRequest = new InteractionRequest<SaveBrowserDialogViewModel>();
public BackupViewModel(IBackupCommandService commandService, ISaveBrowserDialogViewModel saveBrowserDialog)
{
if(commandService == null)
throw new ArgumentNullException("commandService");
if(saveBrowserDialog == null)
throw new ArgumentNullException("saveBrowserDialog");
this.commandService = commandService;
this.saveBrowserDialog = saveBrowserDialog;
this.backupCommand = new DelegateCommand(Backup);
}
private void Backup()
{
saveBrowserDialog.Filters = "Zip archive (*.zip)|*.zip";
saveDialogRequest.Raise((SaveBrowserDialogViewModel)saveBrowserDialog);
if (saveBrowserDialog.Confirmed)
{
commandService.BackupDatabase(saveBrowserDialog.Path);
}
}
}
公共类BackupViewModel:InteractionRequestNotificationObject
{
专用只读DelegateCommand backupCommand;
专用只读IBackupCommandService命令服务;
private readonly InteractionRequest saveDialogRequest=新建InteractionRequest();
公共备份视图模型(IBackupCommandService commandService,ISaveBrowserDialogViewModel saveBrowserDialog)
{
if(commandService==null)
抛出新的ArgumentNullException(“commandService”);
如果(saveBrowserDialog==null)
抛出新ArgumentNullException(“saveBrowserDialog”);
this.commandService=commandService;
this.saveBrowserDialog=saveBrowserDialog;
this.backupCommand=新的DelegateCommand(备份);
}
私有无效备份()
{
saveBrowserDialog.Filters=“Zip存档(*.Zip)|*.Zip”;
saveDialogRequest.Raise((SaveBrowserDialogViewModel)saveBrowserDialog);
如果(saveBrowserDialog.confirm)
{
backUpdatebase(saveBrowserDialog.Path);
}
}
}
我编写了单元测试:
[TestFixture]
public class BackupViewModelTests
{
private BackupViewModel sut;
private Mock<IBackupCommandService> backupCommandServiceMock;
private Mock<ISaveBrowserDialogViewModel> saveDialogMock;
[SetUp]
public void Setup()
{
backupCommandServiceMock = new Mock<IBackupCommandService>();
saveDialogMock = new Mock<ISaveBrowserDialogViewModel>();
sut = new BackupViewModel(backupCommandServiceMock.Object, saveDialogMock.Object);
}
[Test]
public void BackupViewModelShouldCallBackupFromCommandService()
{
saveDialogMock.Setup(x => x.Confirmed).Returns(true);
sut.BackupCommand.Execute(null);
backupCommandServiceMock.Verify(x => x.BackupDatabase(It.IsAny<string>()),Times.Once());
}
}
[TestFixture]
公共类BackupViewModelTests
{
私有备份视图模型sut;
私有模拟备份CommandServiceMock;
私有Mock-saveDialogMock;
[设置]
公共作废设置()
{
backupCommandServiceMock=new Mock();
saveDialogMock=new Mock();
sut=新的BackupViewModel(backupCommandServiceMock.Object、saveDialogMock.Object);
}
[测试]
public void backupviewmodels应调用backupfromcandservice()
{
saveDialogMock.Setup(x=>x.confirm)。返回(true);
sut.BackupCommand.Execute(null);
backupCommandServiceMock.Verify(x=>x.backUpdatebase(It.IsAny()),Times.Once());
}
}
现在我还不知道如何模拟saveDialogRequest。提高(..)以便它可以处理模拟对象,而不是真正的SaveBrowserDialogViewModel。最简单的答案是在静态类
InteractionRequest的周围插入一个'seem'(请参见Michael Feathers的《有效处理遗留代码》)
这意味着将其推到接口(和实现)后面,然后向AutoFac注册此接口和实现,然后将实例作为构造函数参数传递给ViewModel类。这将允许您在测试中模拟接口
大概是这样的:
public interface IInteractionRequestWrapper<T>
{
void Request(T instance);
}
public class InteractionRequestWrapper<T> : IInteractionRequestWrapper<T>
{
private InteractionRequest<T> _saveDialogRequest;
public InteractionRequestWrapper()
{
_saveDialogRequest = new InteractionRequest<T>();
}
public void Request(T instance)
{
_saveDialogRequest.Request(instance);
}
}
公共接口IInteractionRequestWrapper
{
无效请求(T实例);
}
公共类InteractionRequestWrapper:IInteractionRequestWrapper
{
私有交互请求_saveDialogRequest;
公共交互请求包装器()
{
_saveDialogRequest=新的InteractionRequest();
}
公共无效请求(T实例)
{
_saveDialogRequest.Request(实例);
}
}