使用 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 实例,所以不是模拟的,所以它覆盖了模拟。
我知道这是一个老生常谈的错误,但现在我因为工作而感到疲倦。
再次感谢您!
更新:
添加了请求的 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 实例,所以不是模拟的,所以它覆盖了模拟。
我知道这是一个老生常谈的错误,但现在我因为工作而感到疲倦。
再次感谢您!