将Microsoft.Extensions.Logging.Abstractions从Version = 2.0.0.0更新到Version = 3.1.1.0后,我的某些单元测试失败。
我模拟了一个ILogger:
<INPUT id=TBPRODDESC33333 value=0 name=TBPRODDESC33333 InStock="5">
已经建立了一个验证对Log()的调用的单元:
var loggerMock = new Mock<ILogger<BillingEventProcessor>>();
loggerMock.Setup(l => l.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<IReadOnlyList<KeyValuePair<string, object>>>(),
It.IsAny<Exception>(),
It.IsAny<Func<object, Exception, string>>()));
在更新之前,logger.Verify(l => l.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<IReadOnlyList<KeyValuePair<string, object>>>(),
It.IsAny<Exception>(),
It.IsAny<Func<object, Exception, string>>())
);
类型为IReadOnlyList<KeyValuePair<string, object>>
类型。
在v2中,FormattedLogValues是一个公共类,但在v3.1.1中,FormattedLogValues是一个内部只读结构。这种变化似乎与测试失败有关。
我尝试将It.IsAny用作第三个参数,而不是IReadOnlyList或FormattedLogValues,但我对此没有任何运气。
谁知道我可以如何更改此测试代码以使测试通过?从调试信息中可以看到,对Log方法的调用按预期进行,只是无法弄清楚如何使用内部readonly struct参数正确设置这些模拟。
这是一个.NET Core 2.2项目。
答案 0 :(得分:0)
FormattedLogValues
已更改为internal,这有点不方便。使用Moq的常见解决方案是使用It.IsAnyType
:
loggerMock.Verify(l => l.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<It.IsAnyType>(),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
我通常希望从验证中获得更多信息,至少检查一下消息:
loggerMock.Verify(l => l.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.Is<It.IsAnyType>((o, t) => ((IReadOnlyList<KeyValuePair<string, object>>)o).Last().Value.ToString().Equals(message)),
It.IsAny<Exception>(),
(Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
Times.Once);
作为旁注,您提到您正在设置记录器模拟。我想不起来我明确设置了记录器模拟程序的时间,因为通常没有任何必要。
最后,如果您像我一样经常在无头的黑匣子中这样做,请考虑使用contrib库Moq.Contrib.ExpressionBuilders.Logging,它可以解决上述所有问题,并提供流利的构建器以轻松创建verify表达式。免责声明,我是作者。