繁体   English   中英

以下设置不匹配,使用Moq进行WPF MVVM单元测试

[英]The Following Setups were Not Matched, WPF MVVM Unit Testing with Moq

我正在用MoqWPF中编写单元测试,以测试用户关闭窗口时是否单击YesNoCancel MessageBox上的“是”按钮。 当用户关闭窗口时,在ViewModel中的CloseCommand我会给出以下消息:

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

注意: MessageBoxButtonMessageBoxIconMessageBoxResult是我在同一文件中进行的枚举,以模仿.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 ,而是需要捕获结果。

谢谢

这行不通。 您的测试代码中有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();
}

当前,您正在测试将被调用的代码之后,设置模拟方法。 将您的测试重新排列为AAA(排列,执行,声明)模式,如下所示:

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

暂无
暂无

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

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