I’ve previously written about some Unusual things to do with a Console Application, including creating a game in a console application.
This post covers another unusual thing to want to do, but I was recently writing a console application, and wondered how you could test it. That is, without mocking the Console out completely. It turns out that, not only is this possible, it’s actually quite straightforward.
The key here are the methods Console.SetIn and Console.SetOut. These allow you to redirect the console input and output. Let’s take the Hello World example - to unit test this, the first thing to do is to redirect the Console.Out:
var writer = new StringWriter();
Console.SetOut(writer);
You can now unit test this by simply checking the StringWriter:
[Fact]
public void HelloWorldTest()
{
// Arrange
var writer = new StringWriter();
Console.SetOut(writer);
// Act
RunHelloWorld();
// Assert
var sb = writer.GetStringBuilder();
Assert.Equal("Hello, World!", sb.ToString().Trim());
}
You can similarly test an input; let’s take the following method:
public static void GetName()
{
Console.WriteLine("What is your name?");
string name = Console.ReadLine();
Console.WriteLine($"Hello, {name}");
}
We can test both the input and the output of this method:
[Fact]
public void GetNameTest()
{
// Arrange
var writer = new StringWriter();
Console.SetOut(writer);
var textReader = new StringReader("Susan");
Console.SetIn(textReader);
// Act
GetName();
// Assert
var sb = writer.GetStringBuilder();
var lines = sb.ToString().Split(Environment.NewLine, StringSplitOptions.TrimEntries);
Assert.Equal("Hello, Susan", lines[1]);
}
I’m not saying it’s necessarily good practice to unit test, what is essentially, logging, but it’s interesting to know that it’s possible!