如何使ViewModel中的InteractionRequest可测试?

时间:2014-07-25 14:58:20

标签: c# wpf unit-testing moq

我在.Net 4.0上使用PRISM和autofac for WPF,我想开发一个可测试的ViewModels。为了测试我们使用nUnit和moq进行模拟。

所以我有一个班级:

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);
          }
      }
   }

我已经写了单元测试:

[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());
    }
}

现在我还不知道如何模拟saveDialogRequest.Raise(..)以及它可以用于模拟对象,而不是真正的SaveBrowserDialogViewModel。

1 个答案:

答案 0 :(得分:0)

最简单的答案是插入一个&#39;似乎&#39; (请参阅Michael Feathers的“有效使用遗留代码”)围绕静态类InteractionRequest<SaveBrowserDialogViewModel>

这意味着将其推送到接口(和实现)之后,然后使用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);
    }
}