如何使用 Moq 在 .NET Core 3.1 中对 LoggerMessage.Define() 进行单元测试?

Ben*_*min 2 c# moq xunit .net-core

我正在尝试使用 xUnit 中的 Moq 库对 LoggerMessage.Define() 的一些用法进行单元测试,但无法弄清楚。下面是我创建的日志记录函数的示例,下面是一个示例单元测试,无法检查它是否被调用。

LoggerMessage.Define() 示例:

public static class GlobalExceptionLoggerMessage
{
    public static Action<ILogger, string, Exception> GlobalException = LoggerMessage.Define<string>(
        LogLevel.Error,
        new EventId(StatusCodes.Status500InternalServerError, nameof(GlobalException)),
        "{Message}");

    public static void LogGlobalException(this ILogger logger, string message, Exception exception)
    {
        GlobalException(logger, message, exception);
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试过的单元测试示例:

[Fact]
public void LogGlobalExceptionLogTest()
{
    var loggerMock = new Mock<ILogger<object>>();

    var exception = new Exception("Person must exist.");
    const string message = "Person must exist for an object.";

    loggerMock.Object.LogGlobalException(message, exception);

    loggerMock.Verify(
        x => x.Log(
            It.IsAny<LogLevel>(),
            It.IsAny<EventId>(),
            It.Is<It.IsAnyType>((v, t) => true),
            It.IsAny<Exception>(),
            It.Is<Func<It.IsAnyType, Exception, string>>((v, t) => true)));
}
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我如何解决这个问题吗?

谢谢!

rgv*_*lee 10

您需要进行一些额外的设置。如果您查看静态Define方法内部,您将看到以下内容:

if (!logger.IsEnabled(logLevel))
  return;
Log(logger, arg1, exception);
Run Code Online (Sandbox Code Playgroud)

您尚未IsEnabled在模拟记录器上进行设置,因此它将返回默认布尔值 (false) 并且不会调用 Log 方法。

如果您添加以下内容,则获取您的样本:

loggerMock.Setup(x => x.IsEnabled(It.IsAny<LogLevel>())).Returns(true);
Run Code Online (Sandbox Code Playgroud)

...您的验证语句开始工作。

工作示例