Я написал игровое консольное приложение life и сейчас пишу для него юнит-тесты. Игровое поле отображается в виде петли, которая может быть разорвана нажатием 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);
}
}