使用 Moq 进行单元测试时如何绕过(自定义)MessageBoxes?

How to bypass (custom) MessageBoxes when unit testing with Moq?

更新:

添加了请求的 table 绘图代码,其中调用了 MessageBoxService.Show()。

/// <summary>
    /// Draws the classic sudoku table with the given size.
    /// </summary>
    protected override void Draw(object o)
    {
        if (GetCurrentTableViewModel() != null && GetCurrentTableViewModel().AreAnyCellsFilled())
        {
            var messageBoxResult = MessageBoxService.Show(
               Resources.MessageBox_DrawIfNumbersArePresented,
               Resources.MessageBox_Question_Title, MessageBoxButton.YesNo, MessageBoxImage.Question);

            if (messageBoxResult == MessageBoxResult.No || messageBoxResult == MessageBoxResult.Cancel)
            {
                return;
            }
        }

        SudokuBoardSize sudokuBoardSize = (SudokuBoardSize)o;

        bool oldDiagonalRulesStatus = AreDiagonalRulesApplied;
        if (sudokuBoardSize.Height == 9 && sudokuBoardSize.Width == 9)
        {
            SudokuBoardControl = new UcClassicSudoku9x9Table();
            _actualSudokuBoard = CreateBoard(sudokuBoardSize, (BaseSudokuTableViewModel)SudokuBoardControl.DataContext, false);
        }
        else if (sudokuBoardSize.Height == 6 && sudokuBoardSize.Width == 6)
        {
            SudokuBoardControl = new UcClassicSudoku6x6Table();
            _actualSudokuBoard = CreateBoard(sudokuBoardSize, (BaseSudokuTableViewModel)SudokuBoardControl.DataContext, false);
        }
        else
        {
            SudokuBoardControl = new UcClassicSudoku4x4Table();
            _actualSudokuBoard = CreateBoard(sudokuBoardSize, (BaseSudokuTableViewModel)SudokuBoardControl.DataContext, false);
        }

        ((BaseClassicSudokuTableViewModel)SudokuBoardControl.DataContext).AreDiagonalRulesApplied = oldDiagonalRulesStatus;
        SolutionCounter = string.Empty;
        IsSolutionCounterVisible = false;
        _solutions.Clear();
    }

我是 Whosebug 的新手,如有任何错误,敬请谅解。

我正在开发一个数独求解器爱好项目,我想向其中添加单元测试。它完全是 MVVM。 (https://github.com/denesdavid/Solvedoku)

我想在当前数独中至少有一个填充单元格时测试 'the drawing of a new empty table' 功能。在这种情况下,软件会询问您是否真的要绘制新的。我想绕过这个问题,我的意思是......模拟按下是按钮。我读到 Moq 非常适合这个,但目前对我不起作用。单元测试时弹出问题,我必须手动点击是。

这是我的测试:

[TestMethod]
    public void Draw9x9TableWithAlreadyFilledCellsTest()
    {
        Mock<IMessageBoxService> messageBoxMock = new Mock<IMessageBoxService>(MockBehavior.Strict);
        messageBoxMock.Setup(m =>
            m.Show(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<MessageBoxButton>(),
            It.IsAny<MessageBoxImage>()));
        messageBoxMock.SetReturnsDefault(MessageBoxResult.OK);
        
        ClassicSudokuViewModel classicSudokuViewModel = new ClassicSudokuViewModel(messageBoxMock.Object);
        SudokuBoardSize sudokuBoardSize = new SudokuBoardSize();
        sudokuBoardSize.Height = 9;
        sudokuBoardSize.Width = 9;
        sudokuBoardSize.BoxCountX = 3;
        sudokuBoardSize.BoxCountY = 3;

        
        BaseSudokuTableViewModel tableViewModel = classicSudokuViewModel.GetCurrentTableViewModel();
        tableViewModel.Cells[0][0] = "1";
        classicSudokuViewModel.DrawSudokuCommand.Execute(sudokuBoardSize);
        object actualBoard = classicSudokuViewModel.SudokuBoardControl;
        tableViewModel = classicSudokuViewModel.GetCurrentTableViewModel();

        Assert.AreEqual(typeof(UcClassicSudoku9x9Table), actualBoard.GetType());
        Assert.AreEqual(string.Empty, tableViewModel.Cells[0][0]);
        Assert.AreEqual(false, classicSudokuViewModel.AreDiagonalRulesApplied);
        Assert.AreEqual(string.Empty, classicSudokuViewModel.SolutionCounter);
        Assert.AreEqual(false, classicSudokuViewModel.IsSolutionCounterVisible);
        Assert.AreEqual(0, classicSudokuViewModel.Solutions.Count);
    }

IMessageBoxService:

public interface IMessageBoxService
{
    /// <summary>
    /// Shows a MessageBox with the given text, title, button(s) and image.
    /// </summary>
    /// <param name="messageText">Text of the MessageBox.</param>
    /// <param name="title">Title of the MessageBox</param>
    /// <param name="messageBoxButton">Button(s) of the MessageBox</param>
    /// <param name="messageBoxImage">Image of the MessageBox</param>
    /// <returns>MessageBoxResult</returns>
    MessageBoxResult Show(string messageText, string title, MessageBoxButton messageBoxButton,
        MessageBoxImage messageBoxImage);

    /// <summary>
    /// Shows a MessageBox with the given text, title, button(s), image and style.
    /// </summary>
    /// <param name="messageText">Text of the MessageBox.</param>
    /// <param name="title">Title of the MessageBox</param>
    /// <param name="messageBoxButton">Button(s) of the MessageBox</param>
    /// <param name="messageBoxImage">Image of the MessageBox</param>
    /// <param name="messageBoxStyle">Style of the MessageBox</param>
    /// <returns>MessageBoxResult</returns>
    MessageBoxResult Show(string messageText, string title, MessageBoxButton messageBoxButton,
        MessageBoxImage messageBoxImage, Style messageBoxStyle);
}

}

消息框服务:

class MessageBoxService : DependencyObject, IMessageBoxService
{
    private Style _messageBoxStyle = (Style)Application.Current?.Resources["MessageBoxStyle"];

    /// <summary>
    /// Displays a messagebox with the given parameters.
    /// </summary>
    /// <param name="messageText">Text of the messagebox.</param>
    /// <param name="title">Title of the messagebox.</param>
    /// <param name="messageBoxButton">Displayed button(s) in the messagebox. (Choose from the MessageBoxButton enum.).</param>
    /// <param name="messageBoxImage">Displayed icon in the messagebox. (Choose from the MessageBoxImage enum.).</param>
    /// <returns>MessageBoxResult</returns>
    public MessageBoxResult Show(string messageText, string title, MessageBoxButton messageBoxButton, MessageBoxImage messageBoxImage)
    {
        return Xceed.Wpf.Toolkit.MessageBox.Show(Application.Current?.MainWindow, messageText, title, messageBoxButton, messageBoxImage, _messageBoxStyle);
    }

    /// <summary>
    /// Displays a messagebox with the given parameters.
    /// </summary>
    /// <param name="messageText">Text of the messagebox.</param>
    /// <param name="title">Title of the messagebox.</param>
    /// <param name="messageBoxButton">Displayed button(s) in the messagebox. (Choose from the MessageBoxButton enum.).</param>
    /// <param name="messageBoxImage">Displayed icon in the messagebox. (Choose from the MessageBoxImage enum.).</param>
    /// <param name="messageBoxStyle">Style what is applied on the MessageBox.</param>
    /// <returns>MessageBoxResult</returns>
    public MessageBoxResult Show(string messageText, string title, MessageBoxButton messageBoxButton, MessageBoxImage messageBoxImage, Style messageBoxStyle)
    {
        return Xceed.Wpf.Toolkit.MessageBox.Show(Application.Current?.MainWindow, messageText, title, messageBoxButton, messageBoxImage, messageBoxStyle);
    }
}

}

感谢您的帮助!

问题解决

感谢@vernou 的宝贵时间和帮助。问题出在 BaseSudokuTableViewModel class,它被称为 ViewModelBase class,带有一个全新的 MessageBoxService 实例,所以不是模拟的,所以它覆盖了模拟。

我知道这是一个老生常谈的错误,但现在我因为工作而感到疲倦。

再次感谢您!