web-dev-qa-db-ja.com

asp.netコアのビルトインIloggerをテストする方法

ログに記録されたいくつかのログを確認したい。私はasp.netコアの組み込みILoggerを使用しており、asp.netコアの組み込みDIを注入しています。

_private readonly ILogger<InvoiceApi> _logger;

public InvoiceApi(ILogger<InvoiceApi> logger)
{
    _logger = logger;
}
_

その後、次のように使用します:_logger.LogError("error));

私はいつものように(moqで)それをモックしようとしました:

_MockLogger = new Mock<ILogger<InvoiceApi>>();
_

次の方法でテスト用にこれをサービスに挿入します。

_new InvoiceApi(MockLogger.Object);
_

次に検証を試みました:

_MockLogger.Verify(m => m.LogError(It.Is<string>(s => s.Contains("CreateInvoiceFailed"))));
_

しかし、それは投げます:

非仮想(VBでオーバーライド可能)メンバーの無効な検証:m => m.LogError

だから、このログがログに記録されていることを確認するにはどうすればよいですか?

31
arielorvits

@Nkosiが既に言ったように、拡張メソッドをモックすることはできません。あなたがすべきモックは、 ILogger.Logメソッド 、これは LogError呼び出し) 。検証コードが少し不格好になりますが、動作するはずです:

MockLogger.Verify(
    m => m.Log(
        LogLevel.Error,
        It.IsAny<EventId>(),
        It.Is<FormattedLogValues>(v => v.ToString().Contains("CreateInvoiceFailed")),
        It.IsAny<Exception>(),
        It.IsAny<Func<object, Exception, string>>()
    )
);

(これがコンパイルされるかどうかはわかりませんが、要点はわかります)

61
khellang

私は 短い記事 を書きました。他の回答で説明されているように、基礎となるLog()メソッドをモックするなど、さまざまなアプローチを示しています。この記事には、 異なるオプションのそれぞれを備えた完全なGitHubリポジトリ が含まれています。最終的に、呼び出されることをテストする必要がある場合、ILoggerタイプを直接操作するのではなく、独自のアダプターを使用することをお勧めします。

https://ardalis.com/testing-logging-in-aspnet-core

5
ssmith

LogError は、インスタンスメソッドではなく、拡張メソッド(静的)です。静的メソッド(拡張メソッド)をモックフレームワークで「直接」モックすることはできないため、Moqはモックできないため、そのメソッドを検証できません。ターゲットインターフェイスの適応/ラッピングとモックの実行についてオンラインで提案を見てきましたが、多くの場所でコード全体でデフォルトのILoggerを使用している場合は書き換えを意味します。ラッパークラス用とモック可能なインターフェイス用の2つの新しい型を作成する必要があります。

1
Nkosi