[英]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.Show
是static
方法。 如果直接调用它,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.