.NET Core 3.0 ILogger 测试

.NET Core 3.0 ILogger testing

我刚刚从 .NET Core 2.2 迁移到 .NET Core 3.0 并且...我的测试失败了。

以下代码在 .NET Core 2.2 中有效,但在 .NET Core 3.0 中失败

Expected invocation on the mock once, but was 0 times: l => l.Log<object>(LogLevel.Error, 0, It.IsAny<object>(), null, It.IsAny<Func<object, Exception, string>>())

var services = Mock.Of<IServiceCollection>();
var configurationMock = new Mock<IConfiguration>();
var loggerMock = new Mock<ILogger>();

services.AddCustomersConfiguration(configurationMock.Object, loggerMock.Object);

configurationMock.Verify(c => c.GetSection(Customers), Times.Once);
loggerMock.Verify(l => l.Log<object>(LogLevel.Error, (EventId)0, It.IsAny<object>(), null, It.IsAny<Func<object, Exception, string>>()), Times.Once);

所用方法的实现

public static void AddCustomersConfiguration(this IServiceCollection services, IConfiguration configuration, ILogger logger)
{
    logger.LogDebug($"Entering {nameof(AddCustomersConfiguration)} method.");
    var customersSection = configuration.GetSection(CustomersSectionKey);
    if (!customersSection.Exists())
    {
        logger.LogError($"There is no {CustomersSectionKey} section in configuration.");
        return;
    }
}

如果您有任何建议,那将很有帮助

我能够重现错误并通过发现的此版本 .Net Core 的类似问题确定问题

随着最近版本的 Moq 和 It.IsAnyType 的引入,将验证替换为

loggerMock.Verify(l => l.Log(LogLevel.Error, (EventId)0, It.IsAny<It.IsAnyType>(), 
    null, (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()), Times.Once);

按预期工作。

引用https://github.com/moq/moq4/issues/918

除了已接受的答案外,考虑加强断言以包含日志消息

loggerMock.Verify(l => l.Log(
                LogLevel.Error, 
                It.IsAny<EventId>(),
                It.Is<It.IsAnyType>((o, t) => ((IReadOnlyList<KeyValuePair<string, object>>)o).Last().Value.ToString().Equals(expectedLogMessage)),
                null, 
                (Func<It.IsAnyType, Exception, string>) It.IsAny<object>()), 
                Times.Once);

记录值的最后一项(键:OriginalMessage)包含提供给记录方法的消息。