check output in MSTest unit test
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()
{
开发者_JS百科MySnazzyMethod("input", 1, 'c');
string stdOutFromMySnazzyMethod = /* ??? */;
Assert.AreEqual("expected output", stdOutFromMySnazzyMethod);
}
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');
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);
Just add a couple TraceListener in the class initialize of your test classes.
I'd use Moles to redirect the call to Console
writes to a lambda method inside your test code.
string result = "";
System.Moles.MConsole.WriteLineString = (s) =>
{ result = s; };
Assert.IsTrue(result == "The string I want",
"Failed to write to console correctly");
See page 16 in this document: Moles Reference Manual.
精彩评论