Wednesday, June 24, 2015

Capture xUnit Test Output with NLog and Common Logging

I recently blogged about How To Capture Test Output in xUnit 2.0. This is great, but how can we pass the ITestOutputHelper into our code to capture log output?

You could just wrap the xUnit helper in an ILog or ILogger, but we can also take it a step further and get all of the NLog features too! By creating an NLog target that wraps the ITestOutputHelper we can enable ourselves to use multiple targets, layouts, variables, verbosity levels, and more.

Sample Unit Test

public class NLogTests : IDisposable
{
    private readonly ILogger _logger;
 
    public NLogTests(ITestOutputHelper outputHelper)
    {
        _logger = outputHelper.GetNLogLogger();
    }
 
    public void Dispose()
    {
        _logger.RemoveTestOutputHelper();
    }
 
    [Fact]
    public void Hello()
    {
        _logger.Trace("World Trace");
        _logger.Debug("World Debug");
        _logger.Warn("World Warn");
        _logger.Error("World Error");
    }
}

Sample App.config

<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  throwExceptions="true">
  <extensions>
    <add assembly="xunit.NLog" />
  </extensions>
  <targets async="false">
    <target xsi:type="TestOutput"
      layout="${time}|${level:uppercase=true}|${logger}|${message}"
      name="Test" />
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="Test" />
  </rules>
</nlog>

Enjoy,
Tom

3 comments:

  1. _logger = outputHelper.GetNLogLogger(); -- at this line in my code I am getting an exception of an instance not set to an object....having a little trouble understanding why

    ReplyDelete
  2. The App.Config also requires the configSection to be correctly set.
    Eg:






    ...

    ReplyDelete
  3. Eg: ( Not familiar with this editor, but angle brackets are not displayed. So, changed all angle brackets to square brackets to display properly )

    [configuration]
     [configSections]
      [section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" /]
     [/configSections]
     [nlog ...]
     [/nlog]
    [/configuration]

    ReplyDelete

Real Time Web Analytics