这扩展了 Muk 的答案。
我的补充是“ILoggerFactory”..以及您如何“编写”真实班级中的实际日志记录。
一、单元测试代码:
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
private Mock<ILoggerFactory> GetDefaultILoggerFactoryMock()
{
Mock<ILoggerFactory> returnMock = new Mock<ILoggerFactory>(MockBehavior.Loose);
returnMock.Setup(x => x.CreateLogger(It.IsAny<string>())).Returns(
() =>
this.GetDefaultILoggerMock<MyConcreteClassThatUsesILoggerFactoryInItsConstructor>().Object);
return returnMock;
}
private Mock<ILogger<T>> GetDefaultILoggerMock<T>()
{
Mock<ILogger<T>> returnMock = new Mock<ILogger<T>>(MockBehavior.Strict);
returnMock.Setup(
m => m.Log(
It.IsAny<LogLevel>(),
It.IsAny<EventId>(),
It.IsAny<object>(),
It.IsAny<Exception>(),
It.IsAny<Func<object, Exception, string>>())).Callback(
(LogLevel ll, EventId eid, object obj1, Exception ex, Func<object, Exception, string> func) =>
{
Console.WriteLine(func.Invoke(obj1, ex));
}).Verifiable();
returnMock.Setup(m => m.IsEnabled(It.IsAny<LogLevel>())).Returns(false);
return returnMock;
}
现在,在您的实际课程中(这里我称之为“MyConcreteClassThatUsesILoggerFactoryInItsConstructor”)..您需要使用非扩展方法进行日志调用。(所有像 LogInformation 这样的辅助方法都是静态扩展方法重载)
所以像这样:
Func<object, Exception, string> logMsgFunc = (a, b) => "MyDebugMessageOne";
this.logger.Log(LogLevel.Debug, ushort.MaxValue, null, null, logMsgFunc);
或者对于一个例外
catch (Exception ex)
{
Func<object, Exception, string> logMsgFunc = (a, b) => "MyErrorContextMessageTwo";
this.logger.Log(LogLevel.Error, ushort.MaxValue, null, ex, logMsgFunc);
}
如果你做这两件事,尤其是第二部分,你可以模拟 ILoggerFactory / ILogger
这是类/构造函数的密切相关部分:
using Microsoft.Extensions.Logging;
public class MyConcreteClassThatUsesILoggerFactoryInItsConstructor : IMyConcreteClassThatUsesILoggerFactoryInItsConstructor
{
public const string ErrorMsgILoggerFactoryIsNull = "ILoggerFactory is null";
private readonly ILogger<MyConcreteClassThatUsesILoggerFactoryInItsConstructor> logger;
public MyConcreteClassThatUsesILoggerFactoryInItsConstructor(
ILoggerFactory loggerFactory)
{
if (null == loggerFactory)
{
throw new ArgumentNullException(ErrorMsgILoggerFactoryIsNull, (Exception)null);
}
this.logger = loggerFactory.CreateLogger<MyConcreteClassThatUsesILoggerFactoryInItsConstructor>();
}
public void DoSomething()
{
Func<object, Exception, string> logMsgFunc = (a, b) => "DoSomething Started";
this.logger.Log(LogLevel.Debug, ushort.MaxValue, null, null, logMsgFunc);
int div = 0;
try
{
int x = 1 / div;
}
catch (Exception ex)
{
Func<object, Exception, string> errorMsgFunc = (a, b) => string.Format("MyErrorContextMessageTwo (div='{0}')", div);
this.logger.Log(LogLevel.Error, ushort.MaxValue, null, ex, errorMsgFunc);
}
}
}