views:

402

answers:

3

I want to capture output sent to standard out and standard error within an MSTest unit test so that I can verify it. I've captured output before when explicitly running a Process, but is there a way to do with [I guess] the MSTest process itself? For example:

[TestMethod]
public void OutputTest()
{
    MySnazzyMethod("input", 1, 'c');
    string stdOutFromMySnazzyMethod = /* ??? */;
    Assert.AreEqual("expected output", stdOutFromMySnazzyMethod);
}
A: 

Just add a couple TraceListener in the class initialize of your test classes.

Sky Sanders
+1  A: 

I'm not sure there is a way to grab the output of an already running Process. What you could do though is refactor your code slightly to not write to Console.WriteLine but instead take in a TextWriter instance and write to that.

In production you can then just pass Console.Out to the method. In test code you could mock this type and provide much more accurate testing. For example

[TestMethod]
public void OutputTest()
{
    var writer = new Mock<TextWriter>(MockBehavior.Strict);
    writer.Setup(x => x.WriteLine("expected output")).Verifiable();
    MySnazzyMethod(writer.Object, "input", 1, 'c');
    writer.Verify();
}

Production Code

MySnazzyMethod(Console.Out, "input", 1, 'c');
JaredPar
+1  A: 

I liked JaredPar's idea but I didn't want to pass in Console.Out and Console.Error to every helper output method I had. However, my output does go through a single class, so I just set a couple static fields in it:

internal static TextWriter _stdOut = Console.Out;
internal static TextWriter _stdErr = Console.Error;

I updated my output methods in the output handler class to make use of these fields. I then updated that project's AssemblyInfo.cs to include:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyTestProject")]

This way, I can override _stdOut and _stdErr in my test methods, call my method to be tested (which uses my output handling class), and confirm the output I expected.

OutputHandler._stdOut = new StringWriter();
MySnazzyMethod("input", 1, 'c');
OutputHandler._stdOut.Flush();
string expected = "expected output";
string stdout = OutputHandler._stdOut.ToString().Trim(new[] { '\r', '\n' });
Assert.IsFalse(string.IsNullOrEmpty(stdout));
Assert.AreEqual(expected, stdout);
Sarah Vessels