2
votes

This is a follow up from Grabbing the output sent to Console.Out from within a unit test? and the referenced article in the accepted answer by Mark Seemann.

I would like to use Console.Out and Console.In to redirect the streams while testing. Every test in the class needs to use the redirects.

In order to keep the tests clean I would like to do this in the test SetUp and TearDown.

This is what I was thinking:

private StringWriter _sw;
private StringReader _sr;
[SetUp]
public void SetUp()
{
    _sw = new StringWriter();
    Console.SetOut(_sw);
    _sr = new StringReader("100");
    Console.SetIn(_sr);
}

[TearDown]
public void TearDown()
{
    var standardOut = new StreamWriter(Console.OpenStandardOutput());
    standardOut.AutoFlush = true;
    Console.SetOut(standardOut);
    Console.SetIn(new StreamReader(Console.OpenStandardInput()));
 }

Then I would use '_sw.ToString()' within the tests to verify what was written to the stream.

Are there any major drawbacks of using setup or teardown methods for this? Would this similar to redirecting with a using statement? E.g.

using (StringWriter sw = new StringWriter())
{
    ...
}
1

1 Answers

2
votes

Are there any major drawbacks of using setup or teardown methods for this?

Yes, although it may not be measurable.

The way Setup and TearDown method is described here, two new disposable objects are created for every test, but they are never disposed of. They'll eventually go out of scope and be finalised when the garbage collector runs, but it may happen in a less deterministic fashion. In theory, it'll use more memory and processor instructions than if they were deterministically disposed of, but as Knuth taught us 40 years ago, we should measure instead of engaging in premature optimisations.

My main problem with using mutable state and Implicit Setup and Teardown is that it's not thread-safe, so if you ever want to run your unit tests in parallel, you can't.