【问题标题】:How to use NLog in xUnit tests from .NET Core?如何在.NET核心XUnit测试中使用nlog?
【发布时间】:2021-09-07 00:39:12
【问题描述】:

我正在尝试通过 NLog 日志库从基于 .NET Core 3.1 的 xUnit 测试用例中输出一些日志消息。通过 NLog 进行日志记录在我的主应用程序中工作正常,但测试用例不会输出任何消息。

认为我正在做这个相关问题中建议的一切:NLog works in ASP.NET Core App but not in .NET Core xUnit Test Project

但不知何故,我无法弄清楚缺少什么。我已将我的代码简化为一个看起来非常简单的最小示例,但仍然没有输出任何内容:

using NLog;
using NLog.Config;
using NLog.Targets;
using System;
using Xunit;
using Xunit.Abstractions;

namespace UnitTests
{
    public class LoggingTest
    {
        public LoggingTest(ITestOutputHelper output)
        {
            this.output = output;
        }

        private readonly ITestOutputHelper output;

        [Fact]
        public void TestLog()
        {
            var target = new MemoryTarget {Layout = "${message}"};

            LogManager.Configuration ??= new LoggingConfiguration();
            LogManager.Configuration.AddRuleForAllLevels(target);

            LogManager.GetCurrentClassLogger().Info("Hello, World!");

            output.WriteLine("{0} line(s) logged:\n{1}", target.Logs.Count, String.Join("\n", target.Logs));
        }
    }
}

预期输出:

已记录 1 行:
你好,世界!

实际输出:

0 行记录:


作为进一步的跟踪,我在各个地方读到,如果 appsettings.json 文件的 Logging 部分中存在某些设置,NLog 只会在 .NET Core 3.1 项目中写入一些内容。我认为这部分也必须添加到我们的主应用程序的appsettings.json 文件中。

不过,我不确定如何将这些知识转移到单元测试中,因为它们似乎没有附带appsettings.json 文件。我尝试将 appsettings.json 主文件复制到单元测试的输出目录(我认为,这是从 ReSharper 中运行时它们的执行目录),但无济于事。


我错过了什么?

【问题讨论】:

    标签: c# unit-testing .net-core nlog xunit


    【解决方案1】:

    要应用配置,您需要分配 LogManager.Configuration,如

    LogManager.Configuration = config;
    

    工作示例:

    [Fact]
    public void TestLog()
    {
        var target = new MemoryTarget { Layout = "${message}" };
    
        var config = new LoggingConfiguration();
    
        config.AddRuleForAllLevels(target);
        LogManager.Configuration = config; // <-- assign here
        LogManager.GetCurrentClassLogger().Info("Hello, World!");
    
        output.WriteLine("{0} line(s) logged:\n{1}", target.Logs.Count, String.Join("\n", target.Logs));
    
        Assert.Equal(1, target.Logs.Count);
    }
    

    奖励:并行测试

    奖励,如果您喜欢并行测试(谁不喜欢;))- 创建一个新的 LogFactory 而不是分配全局 LogManager

    像这样:

    
    [Fact]
    public void TestLogParallelSafe()
    {
        var logFactory = new LogFactory();
    
        var target = new MemoryTarget { Layout = "${message}" };
    
        var config = new LoggingConfiguration();
    
        config.AddRuleForAllLevels(target);
        logFactory.Configuration = config;
        logFactory.GetCurrentClassLogger().Info("Hello, World!");
    
        output.WriteLine("{0} line(s) logged:\n{1}", target.Logs.Count, String.Join("\n", target.Logs));
    
        Assert.Equal(1, target.Logs.Count);
    }
    
    

    当然,如果其他代码使用LogManager,则不能断言这些日志。

    .NET Core 集成

    作为进一步的跟踪,我在各个地方读到,如果 appsettings.json 文件的 Logging 部分中存在某些设置,NLog 只会在 .NET Core 3.1 项目中写入一些内容。我认为这部分也必须添加到我们主应用程序的 appsettings.json 文件中。

    这仅在与 ASP.NET Core 集成时才需要 - 例如。当从 Microsoft 注入 ILogger&lt;T&gt; 时。这里不需要。如需进一步参考,请参阅Getting started with ASP.NET Core 3 · NLog/NLog Wiki

    【讨论】:

    • 非常有帮助,谢谢。我的输出现在按预期到达。不过,让我澄清一些事情:“你需要分配 LogManager.Configuration” - 好吧,我已经这样做了:LogManager.Configuration ??= new LoggingConfiguration(); 但是,关键点似乎是我必须这样做这 添加我的规则,否则 NLog 将不会注意到新配置。知道了这一点,我现在可以确认在我的 AddRuleForAllLevels 调用之后写一些看似荒谬的东西,比如 LogManager.Configuration = LogManager.Configuration; 将解决我原始代码中的问题。
    • 关于并行测试,这个建议通常很有意义,但不幸的是,“如果其他代码正在使用 LogManager,则无法断言这些日志。”在我的特殊情况下是一个展示者。如果只是为了测试类本身,我已经可以使用 xUnit 的ITestOutputHelper 来记录东西了。我想要使​​用 NLog 的主要理由正是我不想在我的所有接口中打孔,以便我的测试类可以插入它的日志记录引用,而是使用我可以从任何地方调用的 NLog 的静态 GetLogger 方法。
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2017-05-09
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    相关资源
    最近更新 更多