C# 检查MSTest单元测试中的输出

C# 检查MSTest单元测试中的输出,c#,mstest,stdout,redirectstandardoutput,C#,Mstest,Stdout,Redirectstandardoutput,我想捕获发送到标准输出的输出和MSTest单元测试中的标准错误,以便对其进行验证。我以前在显式运行进程时捕获过输出,但是有没有办法[我猜]处理MSTest进程本身呢?例如: [TestMethod] public void OutputTest() { MySnazzyMethod("input", 1, 'c'); string stdOutFromMySnazzyMethod = /* ??? */; Assert.AreEqual("expected output"

我想捕获发送到标准输出的输出和MSTest单元测试中的标准错误,以便对其进行验证。我以前在显式运行
进程
时捕获过输出,但是有没有办法[我猜]处理MSTest进程本身呢?例如:

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

只需在测试类的类初始化中添加几个。

我不确定是否有方法获取已经运行的
进程的输出。不过,您可以稍微重构代码,使其不写入
控制台。WriteLine
,而是接收
TextWriter
实例并写入该实例

在生产中,您只需将Console.Out传递给该方法即可。在测试代码中,您可以模拟这种类型,并提供更精确的测试。比如说

[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();
}
我喜欢,但我不想将
Console.Out
Console.Error
传递给我拥有的每个助手输出方法。但是,我的输出只经过一个类,所以我只在其中设置了两个静态字段:

internal static TextWriter _stdOut = Console.Out;
internal static TextWriter _stdErr = Console.Error;
我更新了输出处理程序类中的输出方法,以利用这些字段。然后,我更新了该项目的AssemblyInfo.cs,以包括:

[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyTestProject")]
这样,我就可以重写测试方法中的
\u stdOut
\u stdErr
,调用要测试的方法(使用我的输出处理类),并确认我期望的输出

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);

我将使用Moles将调用重定向到
控制台
写入测试代码中的lambda方法

string result = ""; 
System.Moles.MConsole.WriteLineString = (s) =>
  { result = s; }; 
Assert.IsTrue(result == "The string I want", 
     "Failed to write to console correctly"); 

见本文件第16页:

请注意测试类中的静态字段。如果要使用它们,请确保在使用它们的任何测试开始时设置OutputHandler.\u stdOut和/或OutputHandler.\u stdErr。MSTest单元测试套件(非有序测试)以不确定的方式运行,因此您运行的后续测试可能没有将这些字段正确设置为Console.Out和Console.Error,然后才尝试使用这些文本编写器。(TestInitialize()和TestCleanup()也不能保证任何安全性。)我认为需要注意的是,如果您将引用更改为Console.Out,那么您实际上并不是在捕获标准输出,而是在伪造/模拟它。这对于单元测试很好,但如果您尝试测试的是实际的控制台输出,则情况并非如此;它是类的标准字符串表示形式。
string result = ""; 
System.Moles.MConsole.WriteLineString = (s) =>
  { result = s; }; 
Assert.IsTrue(result == "The string I want", 
     "Failed to write to console correctly");