题 从单元测试中抓取发送到Console.Out的输出?


我正在使用NUnit在C#中构建单元测试,并且我想测试主程序实际上输出正确的输出,具体取决于命令行参数。

有没有办法从NUnit测试方法调用 Program.Main(...) 抓住写入Console.Out和Console.Error的所有东西,以便我可以对它进行验证?


33
2018-01-26 12:19


起源


这是一个集成测试而不是单元测试。 - Oliver Hanappi
我同意,我正在重新设计解决方案布局,以便立即反映出来。 - Lasse Vågsæther Karlsen
虽然它处于一个灰色区域,但我实际上并没有调用任何外部程序,只是在我的程序文件中调用代码,但我仍然认为它更像是集成测试而不是单元测试。 - Lasse Vågsæther Karlsen


答案:


您可以将Console In,Out和Error重定向到自定义StringWriters,就像这样

[TestMethod]
public void ValidateConsoleOutput()
{
    using (StringWriter sw = new StringWriter())
    {
        Console.SetOut(sw);

        ConsoleUser cu = new ConsoleUser();
        cu.DoWork();

        string expected = string.Format("Ploeh{0}", Environment.NewLine);
        Assert.AreEqual<string>(expected, sw.ToString());
    }
}

看到 这篇博文 了解详情。


61
2018-01-26 12:27



工作就像一个魅力,谢谢! - Lasse Vågsæther Karlsen
如果您使用Resharper,您将失去所有进一步测试的输出屏幕: - Egor Pavlikhin
@EgorPavlikhin:您应该在每次测试结束时使用重置stdout Console.SetOut(new StreamWriter(Console.OpenStandardError()) (你可能还需要设置 Autoflush 为了真实)。在此之后,它将适用于任何测试运行器,包括R#。 - Abel
@Abel,你的意思是OpenStandardError还是OpenStandardOutput? - Daryn
我试过这个,我似乎不需要Console.SetOut(new StreamWriter(Console.OpenStandardError()) - Daryn


您可以使用此简单类通过using语句获取输出:

public class ConsoleOutput : IDisposable
{
    private StringWriter stringWriter;
    private TextWriter originalOutput;

    public ConsoleOutput()
    {
        stringWriter = new StringWriter();
        originalOutput = Console.Out;
        Console.SetOut(stringWriter);
    }

    public string GetOuput()
    {
        return stringWriter.ToString();
    }

    public void Dispose()
    {
        Console.SetOut(originalOutput);
        stringWriter.Dispose();
    }
}

以下是如何使用它的示例:

using (var consoleOutput = new ConsoleOutput())
{
    target.WriteToConsole(text);

    Assert.AreEqual(text, consoleOutput.GetOuput());
}

您可以在我的博客文章中找到更多详细信息和工作代码示例 - 在单元测试中获取控制台输出


8
2017-11-15 11:56



您还没有阅读自我推广常见问题解答。您发布的每个答案都是指向您博客的链接。 - Andrew Barber