我写了一个生命游戏控制台应用程序,现在我正在为它编写单元测试。游戏棋盘是在一个循环中渲染的,可以通过按Esc键来中断。但是,我不知道该如何在主应用程序类的测试方法中模拟按键操作,因此我的测试目前会无限循环。
Application.cs
public class Application
{
private readonly IGame _game;
private readonly IBoard _board;
private readonly IBoardGenerator _boardGenerator;
private readonly IConsole _console;
public Application(IGame game, IBoard board, IBoardGenerator boardGenerator, IConsole console)
{
_game = game;
_board = board;
_boardGenerator = boardGenerator;
_console = console;
}
public void Run()
{
void RenderBoard()
{
_console.Clear();
_board.Evolve();
_board.Print();
Thread.Sleep(150);
}
LoopUntilButtonPressed(() =>
{
_console.Clear();
_game.NewGame();
_game.SetBoard(_board, _boardGenerator);
LoopUntilButtonPressed(RenderBoard, ConsoleKey.Escape);
}, ConsoleKey.Escape);
}
private void LoopUntilButtonPressed(Action action, ConsoleKey consoleKey)
{
do
{
while (!_console.KeyAvailable)
{
action.Invoke();
}
} while (_console.ReadKey(true) != consoleKey);
}
ApplicationTests.cs
[TestFixture]
public class ApplicationTests
{
private Mock<IGame> _fakeGame;
private Mock<IBoard> _fakeBoard;
private Mock<IBoardGenerator> _fakeBoardGenerator;
private Mock<IConsole> _fakeConsole;
private Application _application;
[SetUp]
public void SetUp()
{
_fakeGame = new Mock<IGame>();
_fakeBoard = new Mock<IBoard>();
_fakeBoardGenerator = new Mock<IBoardGenerator>();
_fakeConsole = new Mock<IConsole>();
_application = new Application(_fakeGame.Object, _fakeBoard.Object, _fakeBoardGenerator.Object, _fakeConsole.Object);
}
[Test]
public void Run_MethodCalled_GameCorrectlySet()
{
_application.Run();
_fakeConsole.Setup(c => c.ReadKey(It.IsAny<bool>())).Returns(ConsoleKey.Escape);
_fakeConsole.Setup(c => c.KeyAvailable).Returns(true);
_fakeGame.Verify(g => g.NewGame(), Times.Once);
}
}
ReadKey
和KeyAvailable
成员即可。 - Nkosiwhile (_console.ReadKey(true) != ConsoleKey.Escape);
。 - Romanwhile(true) {...}
循环内部的内容。 - Nkosi