読者です 読者をやめる 読者になる 読者になる

MSTestのAssertでコンソール出力の文言を比較する

C# .NET MSTest

コンソールアプリの中で標準出力している文言をMSTestでテストしたい

  • テスト対象の戻り値が成功でも状態によって出力される文言が変わるのでテストしておきたい
  • StringWriter でコンソール出力を奪ってからメソッドを実行し、StringReaderで読み出せば良いらしい
[TestClass]
public class HogehogeTest
{
    [TestMethod]
    public void fooという処理でbarという文字列が出てくる()
    {
        string expected = "bar";

        var builder = new StringBuilder();
        var writer = new StringWriter(builder);
        // コンソール出力を奪い取る
        Console.SetOut(writer);

        // テスト対象(このメソッドの中でコンソールに出力している)
        Foo();

        // コンソール出力を読みだす
        var reader = new StringReader(builder.ToString());
        string consoleMessage = reader.ReadToEnd();

        // consoleMessageにexpectedが含まれていればOK
        StringAssert.Contains(consoleMessage, expected);
    }
}
  • StringWriter/StringReader使うときにusingで囲んだ方がいいし、後始末でコンソールを戻すとかあるけど、ざっくりこんな感じ。
  • ここを参考にしました。

How to redirect the standard console output, to assert logmessages written by log4net. – Knowledgebase

追記

  • consoleMessageに改行が含まれているとうまく評価できないようなので以下のようにしました。
StringAssert.Contains(consoleMessage, expected);
 ↓
StringAssert.Contains(consoleMessage.Replace(Environment.NewLine, ""), expected);
  • 変更後ソース
[TestClass]
public class HogehogeTest
{
    [TestMethod]
    public void fooという処理でbarという文字列が出てくる()
    {
        string expected = "bar";

        var builder = new StringBuilder();
        var writer = new StringWriter(builder);
        // コンソール出力を奪い取る
        Console.SetOut(writer);

        // テスト対象(このメソッドの中でコンソールに出力している)
        Foo();

        // コンソール出力を読みだす
        var reader = new StringReader(builder.ToString());
        string consoleMessage = reader.ReadToEnd();

        // consoleMessageにexpectedが含まれていればOK
        StringAssert.Contains(consoleMessage.Replace(Environment.NewLine, ""), expected);
    }
}