2

To enable output in test class, as mentioned in the following answer xUnit.net does not capture console output you need to provide the following setup:

public class OutputTest
{
    private readonly ITestOutputHelper _testOutputHelper;

    public OutputTest(ITestOutputHelper testOutputHelper)
    {
        _testOutputHelper = testOutputHelper;
    }

    [Fact]
    public void MyFact()
    {
        _testOutputHelper.WriteLine("Hello world!");
        //this should result in writing to _testOutputHelper too
        LogManager.GetCurrentClassLogger().Info("Hello world!");
    }
}

How do I connect _testOutputHelper with NLog? Is it possible to write to ITestOutputHelper when there is done some logging by NLog (in application or in referenced library)?

mwal
  • 151
  • 3
  • 10
  • What's the idea here? Write to ITestOutputHelper, that will end up to NLog and write to the File/Console? Why writing directly to NLog? – Julian Aug 23 '20 at 13:11
  • Console in xUnit is disabled. Is it possible to write to ITestOutputHelper when there is done some logging by NLog (in application or in referenced library)? – mwal Aug 24 '20 at 13:07
  • Maybe expand the example in your question? – Julian Aug 24 '20 at 17:38

2 Answers2

2

You can create a custom NLog target that writes to Xunit's ITestOutputHelper:

using NLog;
using NLog.Targets;
using Xunit.Abstractions;

namespace YourNamespace
{
    /// <summary>
    /// Writes log messages to Xunit's ITestOutputHelper.
    /// </summary>
    public class XunitLoggerTarget : TargetWithLayout
    {
        private readonly ITestOutputHelper helper;

        public XunitLoggerTarget(ITestOutputHelper helper)
        {
            this.helper = helper;
        }

        protected override void Write(LogEventInfo logEvent)
        {
            var logMessage = Layout.Render(logEvent);
            helper.WriteLine(logMessage);
        }
    }
}

Then, in your Xunit test classes, add a constructor argument for ITestOutputHelper, and configure NLog to use the XunitLoggerTarget:

using NLog;
using NLog.Config;
using Xunit.Abstractions;

namespace YourNamespace
{
    public class NLoggedTest
    {
        public NLoggedTest(ITestOutputHelper testOutputHelper)
        {
            var config = new LoggingConfiguration();
            var target = new XunitLoggerTarget(testOutputHelper);
            config.AddTarget("Xunit", target);

            config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, target));
            LogManager.Configuration = config;
        }

        // your tests/facts/theories here
    }
}

You could make NLoggedTest an abstract/base class and write your other test classes to inherit from it.

Greg McCoy
  • 511
  • 7
  • 7
0

You can use the NLog MethodCallTarget for calling the testOutputHelper:

public class NLoggedTest
{
    public NLoggedTest(ITestOutputHelper testOutputHelper)
    {
        var target = new NLog.Targets.MethodCallTarget("Xunit", (evt,args) => testOutputHelper.WriteLine(evt.FormattedMessage + evt.Exception?.ToString()));
        var config = new LoggingConfiguration();
        config.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, target));
        LogManager.Configuration = config;
    }

    // your tests/facts/theories here
}

See also: https://github.com/NLog/NLog/wiki/MethodCall-target

Rolf Kristensen
  • 17,785
  • 1
  • 51
  • 70