【问题标题】:NLog works in ASP.NET Core App but not in .NET Core xUnit Test ProjectNLog 适用于 ASP.NET Core 应用程序,但不适用于 .NET Core xUnit 测试项目
【发布时间】:2019-10-25 08:18:51
【问题描述】:

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

每个实现类都使用 NLog。这在包含和引用 .NET Core 类库的 ASP.NET Core Web 应用程序中非常有效。

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

无法将“NLog.Logger”类型的对象转换为“Microsoft.Extensions.Logging.ILogger”类型

我搜索过类似的问题,但没有找到。

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

private readonly ILogger<DatabasePersistenceAdoDotNet> _logger = null;

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

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

这适用于包含和引用 .NET Core 类库的 ASP.NET Core Web 应用程序,但在我的 .NET Core xUnit 测试项目中崩溃了。

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

【问题讨论】:

    标签: c# asp.net-core .net-core nlog


    【解决方案1】:

    在 ASP.NET Core 中使用 NLog 时,有两种样式:

    1. 非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&lt;MyClass&gt;!只是一个非通用的Microsoft.Extensions.Logging.ILogger。如果您需要通用版本,那么您需要 DI 设置,它将处理两者之间的转换。

    NLog.config 和测试项目

    另外很高兴知道,在测试项目中找到 nlog.config 很难,因为单元测试框架会移动二进制文件等。我建议使用 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;
    

    【讨论】:

    • 谢谢,谢谢,谢谢@Julian!您的周到、完整且非常有帮助的答案完全解决了我的问题,同时教会了我一些重要的 NLog 概念。感谢您分享您的经验!
    • 使用NLog.Web.NLogBuilder.ConfigureNLog 而不是仅仅将配置对象分配给LogManager.Configuration 有什么特别之处吗?在我们的主应用程序中,后者运行良好,尽管 I cannot get NLog to output anything in my unit tests,这是我在这里看到你的解释的唯一剩余差异。
    • 不再。但是有 UseNLog (位相关)。无论如何,回答了您的链接问题。它缺少LogManager.Configuration 的分配;)
    猜你喜欢
    • 1970-01-01
    • 2019-01-17
    • 1970-01-01
    • 2018-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-20
    • 1970-01-01
    相关资源
    最近更新 更多