Search code examples
.netunit-testinglog4netxunit2

How to capture log4net output in xunit2


I've read http://xunit.github.io/docs/capturing-output.html and it seems to apply to making my test output specific message during the test running but I would really like to be able to capture the log4net output that is already integrated into the classes I am testing.

In the past i have set up log4net to use a TraceLogger and the test framework was able to associate the output with the test. (different testing framework). How can I somehow associate log4net output to the Xunit IOutputHelper?


Solution

  • This was the answer i came up with

    This is a class I can make my test class inherit from:

       public class LogOutputTester:IDisposable
        {
            private readonly IAppenderAttachable _attachable;
            private TestOutputAppender _appender;
    
            protected LogOutputTester(ITestOutputHelper output)
            {
                log4net.Config.XmlConfigurator.Configure(); 
                var root = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root;
                _attachable = root;
    
                _appender = new TestOutputAppender(output);
                if (_attachable != null)
                    _attachable.AddAppender(_appender);
            }
    
            /// <summary>
            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
            /// </summary>
            public void Dispose()
            {
                _attachable.RemoveAppender(_appender);
            }
        }
    

    this is a custom Appender I made referenced in the above helper:

     public class TestOutputAppender : AppenderSkeleton
        {
            private readonly ITestOutputHelper _xunitTestOutputHelper;
    
            public TestOutputAppender(ITestOutputHelper xunitTestOutputHelper)
            {
                _xunitTestOutputHelper = xunitTestOutputHelper;
                Name = "TestOutputAppender";
                Layout = new PatternLayout("%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n");
            }
    
            protected override void Append(LoggingEvent loggingEvent)
            {
                _xunitTestOutputHelper.WriteLine(RenderLoggingEvent(loggingEvent));
            }
        }
    

    This could be customized more to take a custom layout or whatever...

    Finally - i just make my test class inherit from this helper:

       public class MyTestClass:LogOutputTester
        {
            public EdgeClientTests(ITestOutputHelper output):base(output)
            {
            }
        ...
    

    You could give your tests direct access to the output object too...