NLog 在 ASP.NET Core App 中有效,但在 .NET Core xUnit 测试项目中无效

NLog works in ASP.NET Core App but not in .NET Core xUnit Test Project

我创建了一个 .NET Core class 库,它定义了实用程序 class 接口,并为通过 ADO.NET 访问数据库等实现了每个接口

每个实现 class 都使用 NLog。这在包含并引用 .NET Core class 库的 ASP.NET Core Web 应用程序中效果很好。

但是,当我尝试在 .NET Core xUnit 测试项目的上下文中实例化这些相同的实现 classes 时,我得到

Unable to cast object of type 'NLog.Logger' to type 'Microsoft.Extensions.Logging.ILogger'

我搜索过类似的问题,但找到了 none。

在每个 class 中我都声明了一个私有只读变量:

private readonly ILogger<DatabasePersistenceAdoDotNet> _logger = null;

我正在像这样实例化这个变量:

_logger = (ILogger<DatabasePersistenceAdoDotNet>)NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();

这适用于 ASP.NET 核心 Web 应用程序,该应用程序包含并引用 .NET Core class 库,但在我的 .NET Core xUnit 测试项目中爆炸。

我怀疑这与 ASP.NET 的依赖注入在 .NET Core xUnit 测试项目中不可用有关,但我不知道如何使我的实用程序包正常工作在这两种情况下。

NLog与ASP.NET核心一起使用时,有两种风格:

  1. non-DI 样式,使用 GetCurrentClassLogger()
  2. DI风格,需要NLog.Extensions.Logging / NLog.Web.AspNetCore包来桥接NLog和Microsoft.Extensions.Logging。

当使用 .GetCurrentClassLogger() 时,您将获得一个 NLog 记录器对象(它实现 NLog.ILogger,而不是 Microsoft.Extensions.Logging.ILogger)。

因此,如果您需要 Microsoft.Extensions.Logging.ILogger,则不能使用 .GetCurrentClassLogger()。您需要:

  1. 自己设置整个 DI 系统,构造函数注入 Microsoft.Extensions.Logging.ILogger,或者
  2. 使用 NLog.Extensions.Logging 包的 类。

选项 2 是简单的方法,我将向您展示如何:

// Load NLog
NLog.Web.NLogBuilder.ConfigureNLog("nlog.config");

// Create provider to bridge Microsoft.Extensions.Logging
var provider = new NLog.Extensions.Logging.NLogLoggerProvider();

// Create logger
Microsoft.Extensions.Logging.ILogger logger = provider.CreateLogger(typeof(MyClass).FullName);

请注意,您不能通过这种方式创建 Microsoft.Extensions.Logging.ILogger<MyClass>!只是一个 non-generic Microsoft.Extensions.Logging.ILogger。如果您需要通用版本,那么您需要 DI 设置,它将处理两者之间的转换。

NLog.config 和测试项目

也很高兴知道,在测试项目中找到 nlog.config 很难,因为单元测试框架会移动二进制文件等。我建议使用配置 API

例如

var configuration = new LoggingConfiguration();
configuration.AddRuleForAllLevels(new ConsoleTarget());
LogManager.Configuration = configuration;

var configuration = XmlLoggingConfiguration.CreateFromXmlString("<nlog>....</nlog>"); //full nlog.config as string
LogManager.Configuration = configuration;