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

标签 c# wpf unit-testing mvvm moq

我正在 中编写单元测试WPF 起订量 测试用户是否点击了 YesNoCancel 上的"is"按钮MessageBox 当他们关闭窗口时。在我的 CloseCommand当用户关闭窗口时,我的 ViewModel 中会给出以下消息:

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

我的 _messageSvc是自定义消息服务内部的私有(private)实例,用于显示消息框。这是该服务的代码:
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);
    }
}

注:MessageBoxButton , MessageBoxIcon , 和 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()行,但据我所知,我做得正确。我需要获取消息框的返回值来继续测试用户单击"is"按钮后会发生什么,所以我不想使用 Verify里面有一个 Linq 查询,而不是我需要捕获结果。

谢谢

最佳答案

这行不通。您的测试代码中有 2 个问题:

  • 您首先触发 CloseCommand (假定调用 IMessageSvc.Show 方法),然后才为该服务设置模拟。
  • 您为服务设置了一个新的模拟,但不使用它。

  • 要更正这些错误:
  • 更改顺序,使其成为正确的“排列”-“行为”-“断言”顺序
  • 使用依赖注入(inject)
  • 在 View 模型中注入(inject)您的模拟服务

    这是一个例子:
    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();
    }
    

    关于c# - 以下设置不匹配,使用 Moq 进行 WPF MVVM 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45883759/

    相关文章:

    c# - 值类型相对于引用类型的好处?

    wpf - 获取 DoDragDrop DragSource

    Swift 如何对具有依赖关系的函数进行单元测试

    wpf - 将模型的变化列表同步到 ViewModel 的 ObservableList 的最佳实践?

    java - 如何在junit中建立测试用例?

    python - 有没有办法用 PyCharm 捕获单元测试异常?

    c# - 模拟 DbSet.AddOrUpdate

    c# - 一般的奇怪行为

    c# - MySql.Data.MySqlClient.MySqlException : Duplicate entry

    c# - wpf GUI线程中的线程太慢