2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[.NET Core] xUnit で log を verify する

Posted at

メソッドの戻り値では検証ができないようなケースで、処理内部のログが出力されている/出力されていないによって、予期した通りの動きになっているかをテストしたかった。
Moq の Verify によって、該当ログが出力されているかどうかを確認することで実現する。

環境

  • Visual Studio 2019
  • .NET Core 3.1

準備

  • Visual Studio で 「xUnit テストプロジェクト(.NET Core)」を作成
  • 作成したテストプロジェクトに、NuGet パッケージの管理から「Moq」をインストール

実装

テスト対象

Target.cs
    public class Hoge
    {
        private readonly ILogger<Hoge> logger;

        public Hoge(ILogger<Hoge> logger) => this.logger = logger;

        public bool Fuga()
        {
            try
            {
                // なんかの処理1
                // ~~~
                logger.LogInformation("処理1終わったよ");

                // なんかの処理2
                // ~~~
                logger.LogInformation("処理2終わったよ");

                return true;
            }
            catch
            {
                logger.LogError("例外発生しちゃたよ");
                return false;
            }
        }
    }

テストコード

UnitTest.cs
    public class HogeTest
    {
        private Mock<ILogger<Hoge>> loggerMock = new Mock<ILogger<Hoge>>();

        [Fact]
        public void SuccessTest()
        {
            // 正常終了する条件で Fuga 実行
            new Hoge().Fuga();

            // なんかの処理1ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Information
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("処理1終わったよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Once);  // このログが1回出力されることの確認

            // なんかの処理2ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Information
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("処理2終わったよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Once);  // このログが1回出力されることの確認

            // 例外ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Error
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("例外発生しちゃたよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Never);  // このログが出力されないことの確認
        }

        [Fact]
        public void ExceptionTest()
        {
            // なんかの処理2で例外が発生する条件で Fuga 実行
            new Hoge().Fuga();

            // なんかの処理1ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Information
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("処理1終わったよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Once);  // このログが1回出力されることの確認

            // なんかの処理2ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Information
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("処理2終わったよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Never);  // このログが出力されないことの確認

            // 例外ログの確認
            loggerMock.Verify(l => l.Log(LogLevel.Error
                , It.IsAny<EventId>()
                , It.Is<It.IsAnyType>((object o, Type _) => o.ToString().Contains("例外発生しちゃたよ"))
                , null
                , (Func<It.IsAnyType, Exception, string>)It.IsAny<object>())
            , Times.Once);  // このログが1回出力されることの確認
        }
    }

該当ログメッセージが出力されるか否かを Verify することで、外部から検証し辛い内部の動きを確認することができる。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?