我正在使用 Serilog 的
ForContext()
方法按照 一般指南向日志事件添加自定义属性
问题在于,从我在源代码中看到的,调用 ForContext() 会执行以下操作:
ILogger ForContext(string propertyName, object? value, bool destructureObjects = false)
=> new LoggerConfiguration()
.MinimumLevel.Is(LevelAlias.Minimum)
.WriteTo.Logger(this)
.CreateLogger()
.ForContext(propertyName, value, destructureObjects)
;
它返回一个新对象,因此当我链接这些调用并尝试编写单元测试来断言为每个属性调用了 ForContext 并调用了适当的日志方法时,它总是失败。例如:
public class MyService
{
ILogger _logger;
public MyService (ILogger log)
{
_logger = log
}
public void DoStuff()
{
_logger
.ForContext("One", 1)
.ForContext("Two", 2)
.Warning("Not happy");
}
}
以及以下示例测试:
public class MyServiceTest
{
Mock<ILogger> _loggerMock = new();
MyService sut;
public MyServiceTest(ILogger log)
{
_loggerMock.Setup(x => x.Warning(It.IsAny<string>()).Verifiable();
sut = new MyService(_loggerMock.Object);
}
public void DoStuffShouldLogWarning()
{
sut.DoStuff();
_loggerMock.Verify(x => x.Warning(It.IsAny<string>()), times.once);
}
}
我知道警告从未被调用过,但是
ForContext("One", 1)
被调用了一次,然后 Write()
被调用了......这基本上是正确的。
我怎样才能做到这一点,让我确保其他开发人员(或我)不会随机删除日志中的属性,或使用错误的值,或更改日志级别作为代码的一部分改变。
在 @Jeanot Zubler 的评论后面(感谢您为我指出正确的方向),根据我原来的示例,我这样解决:
_mockLogger.Setup(x => x.ForContext(It.IsAny<string>(), It.IsAny<object>())).Returns(_mockLogger.Object);
然后你可以这样做:
// Verify the for context call
_mockLogger.Verify(o => o.ForContext(It.IsAny<string>(), It.IsAny<int>()), Times.Once());
// Verify the chained warning
_loggerMock.Verify(x => x.Warning(It.IsAny<string>()), times.once);