2017-08-25 29 views
1

我在WPF编写单元测试与起订量来测试用户是否点击了一个YesNoCancel MessageBox中的“是”按钮时,他们关闭窗户。在我CloseCommand我在我的视图模型给出了当用户关闭窗口下面的消息:以下设置不匹配,WPF MVVM单元测试与起订量

var result = _messageSvc.Show(
    "Do you want to save changes?", 
    "Save Changes", 
    Services.MessageBoxButton.YesNoCancel, 
    Services.MessageBoxIcon.Question, 
    Services.MessageBoxResult.Yes); 

_messageSvc是一个自定义邮件服务以显示消息框内部的私有实例。下面是服务的代码:

public interface IMessageSvc 
{ 
    void Show(string message); 
    MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult = 0); 
} 

public class MessageSvc : IMessageSvc 
{ 
    public void Show(string message) 
    { 
     MessageBox.Show(message); 
    } 

    public MessageBoxResult Show(string message, string caption, MessageBoxButton buttons, MessageBoxIcon icon, MessageBoxResult defaultResult) 
    { 
     return (MessageBoxResult)MessageBox.Show(message, caption, (System.Windows.MessageBoxButton)buttons, (System.Windows.MessageBoxImage)icon, (System.Windows.MessageBoxResult)defaultResult); 
    } 
} 

注:MessageBoxButtonMessageBoxIcon,并MessageBoxResult是枚举我在同一个文件进行模仿什么.NET提供开箱即用的。我不向他们展示这里的可读性

我的单元测试的缘故:

[TestMethod] 
public void ShouldAskToSaveOnCloseRespondYesTest() 
{ 
    // Mock and setup initial user data 
    var u= new User 
    { 
     UserId = 1, 
     UserName = "FirstName LastName", 
     FavoriteColor = "Blue" 
    }; 
    mainViewModel.UserInfo= new UserInfoDtoWrapper(u); 

    // assert the data has not changed yet 
    Assert.IsFalse(mainViewModel.UserInfo.IsChanged); 

    // change the user data 
    mainViewModel.UserInfo.UserName= "LastName FirstName"; 

    // assert the data has changed 
    Assert.IsTrue(mainViewModel.UserInfo.IsChanged); 

    // execute window closing 
    mainViewModel.CloseCommand.Execute(new object()); 

    // verify messagebox shows and the 'Yes' button is clicked 
    // this will then save the changes made to the user instance 
    var messageBox = new Mock<IMessageSvc>(); 
    messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
     It.Is<string>(y => y == "Save Changes"), 
     It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
     It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
     It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
     .Returns(MessageBoxResult.Yes); 

    messageBox.Verify(); 
} 

的错误出现在messageBox.Verify()线,但是从我所看到的,我做正确。我需要获取消息框的返回值,以继续测试用户单击“是”按钮后发生的情况,所以我不想在内部使用带有Linq查询的Verify,而是需要捕获结果。

谢谢

+0

“错误发生在messageBox.Verify()行” - 什么错误? –

+0

ShouldAskToSaveOnCloseRespondYesTest引发异常:Moq.MockVerificationException:以下设置不匹配:IMessageSvc x => x.Show(它是(y => y ==“您是否想保存更改吗?”),它是。 (y => y ==“保存更改”)... –

+0

安装和验证之间的其余代码在哪里?目前没有测试执行 –

回答

2

这是行不通的。你在你的测试代码2个问题:

  1. 你先火CloseCommand(假定调用IMessageSvc.Show方法),然后才安装了该服务的模拟。

  2. 您为服务设置了一个新的模拟,但不使用它。

要纠正这些错误:

  • 更改顺序,这是一个正确的“安排” - “行动” - “断言”为了
  • 注入你的嘲笑服务视图模型使用依赖注入

下面是一个例子:

class MainViewModel 
{ 
    private readonly IMessageSvc _messageSvc; 

    public MainViewModel(IMessageSvc svc) 
    { 
     this._messageSvc = svc; 
    } 
} 

[TestMethod] 
public void ShouldAskToSaveOnCloseRespondYesTest() 
{ 
    // Arrange 
    var messageBox = new Mock<IMessageSvc>(); 
    messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
     It.Is<string>(y => y == "Save Changes"), 
     It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
     It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
     It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
     .Returns(MessageBoxResult.Yes) 
     .Verifiable(); 

    var mainViewModel = new MainViewModel(messageBox.Object); 

    // Act 
    mainViewModel.CloseCommand.Execute(new object()); 

    // Assert 
    messageBox.Verify(); 
} 
+0

我将消息服务对象添加到单元测试类初始化的视图模型构造函数,以便从那里注入。然而,在单元测试方法中,在将我的代码按照您展示的方式排列后,我仍然得到相同的错误。 –

+0

@ J-man,不,你没有按照我的建议安排你的代码。您正在测试方法中为您的服务创建一个新的模拟。这个模拟的服务必须提供给视图模型。您必须在测试方法中创建视图模型(如我所建议的那样),或者在创建视图模型的类初始化中设置服务模拟。 – dymanoid

+0

你是对的@dymanoid,当我已经有权访问在单元测试类的初始化方法中注入的类作用域messageSvc对象时,我错误地设置了一个新的我的消息服务的模拟实例。所以我应该设置'messageSvc.Setup(...)'而不是我正在做的'var messageBox = new Mock (); messageBox.Setup(...)'。难怪无法找到正确的设置,因为SAME对象需要注入虚拟机,所以我错误地试图注入一个新对象。谢谢!!我会将你的标记作为答案。 –

0

当前你正在设置你的模拟方法测试将调用它的代码。重新安排您的测试AAA (Arrange, Act, Assert)模式像这样:

var messageBox = new Mock<IMessageSvc>(); 
messageBox.Setup(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
    It.Is<string>(y => y == "Save Changes"), 
    It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
    It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
    It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))) 
    .Returns(MessageBoxResult.Yes); 

mainViewModel.CloseCommand.Execute(new object()); 

messageBox.Verify(x => x.Show(It.Is<string>(y => y == "Do you want to save changes?"), 
    It.Is<string>(y => y == "Save Changes"), 
    It.Is<MessageBoxButton>(y => y == MessageBoxButton.YesNoCancel), 
    It.Is<MessageBoxIcon>(y => y == MessageBoxIcon.Question), 
    It.Is<MessageBoxResult>(y => y == MessageBoxResult.Yes))); 
+0

我以前试过这个,在这种情况下返回的错误是'期望调用模拟一次,但是用'messageBox.Verify(x => x.Show(0)> 0次' y ==“您想保存更改吗?”), It.Is (y => y == ==“Save Changes”), It.Is (y => y == MessageBoxButton.YesNoCancel) , It.Is (y => y == MessageBoxIcon.Question), It.Is (y => y == MessageBoxResult.Yes)),Times.Once);' –

+0

我有我的IMessageService注入ViewModel并在Unit Test类中初始化,所以当我运行_messageSvc.Verify(x => x.Show(It.Is (y => y ==“你想保存更改吗? ) It.Is (y => y == == Save Changes), It.Is (y => y == MessageBoxButton.YesNoCancel), It.Is (y => y = = MessageBoxIcon.Question), It.Is (y => y == MessageBoxResult.Yes)),Times.Once);'它工作,但我需要设置消息框以获取返回值 –