繁体   English   中英

最小起订量测试

[英]Testing with moq

我正在尝试完成整个测试工作,并决定从现有的应用程序开始,我们使用该应用程序记录到办公室的电话呼叫。 该应用程序是ac#,mvvm,桌面应用程序,至少到目前为止,我只是试图确定测试框架的运行方式。 我创建了一个新的测试项目,添加了对moq的引用,并试图运行一个测试来验证一个方法是否被另一个方法调用。

我正在测试的方法仅仅是关闭窗口的命令。 该命令使用消息传递与View Service进行通信以实际完成关闭。 相关代码:

BaseViewModel

public RelayCommand CloseWindowCommand { get; set; }

public BaseViewModel(IDataAccessService dataAccess)
{
  ...
  CloseWindowCommand = new RelayCommand(CloseWindow);
}

internal virtual void CloseWindow()
{
  SendCloseRequest();
}

void SendCloseRequest()
{
  System.Windows.MessageBox.Show("called BaseVM.SendCloseRequest");
  Messenger.Default.Send<RequestCloseMessage>(new RequestCloseMessage(this), this);
}

ViewService

private Window CreateWindow(ViewModelBase vm)
{
  ...
  window.DataContext = vm;
  window.Closed += OnClosed;

  // listen for the close event
  Messenger.Default.Register<RequestCloseMessage>(window, vm, OnRequestClose);
  return window;
}

public void OnRequestClose(RequestCloseMessage message)
{
  System.Windows.MessageBox.Show("called ViewService.OnRequestClose");

  var window = OpenedWindows.SingleOrDefault(w => w.DataContext == message.ViewModel);
  if (window != null)
  {
    Messenger.Default.Unregister<RequestCloseMessage>(window, message.ViewModel, OnRequestClose);
    if (message.DialogResult != null)
    {
      // trying to set the dialog result of the non-modal window will result in InvalidOperationException
      window.DialogResult = message.DialogResult;
    }
    window.Close();
  }
}

BaseViewModelTest (1):

[TestMethod]
public void SendCloseMesage_Calls_OnRequestClose()
{
  Mock<IDataAccessService> mockProxy = new Mock<IDataAccessService>();
  Mock<IViewService> mockView = new Mock<IViewService>();
  var vm = new BaseViewModel(mockProxy.Object);
  Mock<RequestCloseMessage> mockCloseMessage = new Mock<RequestCloseMessage>((ViewModelBase)vm, null);

  vm.CloseWindowCommand.Execute(null);
  mockView.Verify(v => v.OnRequestClose(mockCloseMessage.Object));
}

当我运行测试时,它失败并显示:

Moq.MockException: 
Expected invocation on the mock at least once, but was never performed: v => v.OnRequestClose

因此,我尝试测试该命令是否调用了VM中的方法:

BaseViewModelTest (2):

[TestMethod]
public void SendCloseMesage_Calls_CloseWindow()
{
  Mock<IDataAccessService> mockProxy = new Mock<IDataAccessService>();
  Mock<IViewService> mockView = new Mock<IViewService>();
  //var vm = new BaseViewModel(mockProxy.Object);
  Mock<BaseViewModel> mockVM = new Mock<BaseViewModel>(mockProxy);
  Mock<RequestCloseMessage> mockCloseMessage = new Mock<RequestCloseMessage>((ViewModelBase)mockVM.Object, null);

  mockVM.Object.CloseWindowCommand.Execute(null);
  mockVM.Verify(vm => vm.CloseWindow());
}

这返回一个类似的错误:

Moq.MockException: 
Expected invocation on the mock at least once, but was never performed: vm => vm.CloseWindow()

但是,在两种情况下, System.Windows.MessageBox.Show("called <MethodName>"); 声明被称为,因为我必须处理对话框。 (我添加了MessageBox命令进行确认。无论有没有错误,错误都是相同的。)

当调用方法中的MessageBox.Show()命令时,为什么Moq告诉我未调用该方法?

PS:我并不担心测试关闭窗口是否值得,目前,我只是想确保可以测试一种方法正在调用另一种方法。

首先, 方法MessageBox.Showstatic方法。 如果直接调用它,Moq将没有机会知道。

另外,您是否甚至将mockCloseMessage传递(或注入)到被测对象?

 mockView.Verify(v => v.OnRequestClose(mockCloseMessage.Object)); 

这将确认OnRequestClose是用实例调用至少一次mockCloseMessage.Object ,这似乎并非如此,你的情况。

您应该使用It.IsAny<>() (或其他数学参数函数,请检查docs ):

mockView.Verify(v => v.OnRequestClose(It.IsAny<RequestCloseMessage>()));

更新资料

再次查看您的代码后,还有其他要提的要点:

模拟的想法是当您想要测试依赖于其他类的特定类时。 然后,您将模拟那些依赖项类,以隔离和简化您的测试。

看来您已经创建了一些模拟,但是它们并未注入到您正在测试的对象中。

另一个问题是您对Messenger类有依赖性,必须执行注册过程才能使服务接收事件。 您在这里混合得太多,并作一些假设。 在我看来,您似乎错过了整个单元测试的重点。 您的测试依赖于其他地方发生的动作。

照原样,您的代码似乎不容易测试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM