Is it possible to mock NLog log methods?
Asked Answered
C

4

7

Is it possible/easy to mock NLog log methods, using Rhino Mocks or similar?

Cripps answered 7/2, 2011 at 5:57 Comment(2)
Try looking at slf.codeplex.comWengert
See detailed post Using NLog with Dependency Injection. The post uses NInject as a DI example.Selectman
M
3

You can only mock virtual methods. But if You create some interface for logging and then implement it using NLog You can use dependency injection and in Your tests use mocked interface to see if system under test (SUT) is logging what You expect it to log.

public class SUT
{
  private readonly ILogger logger;
  SUT(ILogger logger) { this.logger = logger;}
  MethodUnderTest() {
    // ...
    logger.LogSomething();
    // ...
  }
}

// and in tests
var mockLogger = new MockLogger();
var sut = new SUT(mockLogger);
sut.MethodUnderTest();
Assert.That("Expected log message", Is.Equal.To(mockLogger.LastLoggedMessage));
Microscopium answered 26/6, 2011 at 8:54 Comment(0)
C
10

Using Nuget : install-package NLog.Interface

Then: ILogger logger = new LoggerAdapter([logger-from-NLog]);

Christeenchristel answered 27/9, 2012 at 17:58 Comment(1)
Simple, but effective. Github project is here if anyone wants to see what it does: github.com/uhaciogullari/NLog.InterfaceDivisionism
M
3

You can only mock virtual methods. But if You create some interface for logging and then implement it using NLog You can use dependency injection and in Your tests use mocked interface to see if system under test (SUT) is logging what You expect it to log.

public class SUT
{
  private readonly ILogger logger;
  SUT(ILogger logger) { this.logger = logger;}
  MethodUnderTest() {
    // ...
    logger.LogSomething();
    // ...
  }
}

// and in tests
var mockLogger = new MockLogger();
var sut = new SUT(mockLogger);
sut.MethodUnderTest();
Assert.That("Expected log message", Is.Equal.To(mockLogger.LastLoggedMessage));
Microscopium answered 26/6, 2011 at 8:54 Comment(0)
N
1

The simple answer, is 'no'. Looking at the code, dependency-injection is not supported, which seems rather an oversight, especially as it doesn't look difficult to implement (at first glance).

The only interfaces in the project are there to support COM interop objects and a few other things. The main Logger concrete class neither implements an interface, nor provides virtual methods.

You could either provide an interface yourself, or use Moles/TypeMock/ another isolation framework to mock the dependency.

Nevillenevin answered 19/2, 2012 at 10:23 Comment(0)
F
0

I've used code like this to stub out the NLog logging code. You can make use of NLog's MemoryTarget which just keeps messages in memory until it's disposed of. You can query the content of the log using Linq or whatever (this example uses FluentAssertions)

    using FluentAssertions
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using NLog;
    using NLog.Config;
    using NLog.Targets;

    ...

    private MemoryTarget _stubLogger;

    [TestInitialize]
    public void Setup()
    {
        ConfigureTestLogging();
    }

    protected virtual LoggingConfiguration GetLoggingConfiguration()
    {
        var config = new NLog.Config.LoggingConfiguration();
        this._stubLogger = new MemoryTarget();

        _stubLogger.Layout = "${level}|${message}";
        config.AddRule(LogLevel.Debug, LogLevel.Fatal, this._stubLogger);

        return config;
    }

    protected virtual void ConfigureTestLogging()
    {
        var config = GetLoggingConfiguration();

        NLog.LogManager.Configuration = config;
    }

    [TestMethod]
    public void ApiCallErrors_ShouldNotThrow()
    {
        // arrange
        var target = new Thing();
        
        // act
        target.DoThing();

        // assert
        this._stubLogger.Logs.Should().Contain(l => 
            l.Contains("Error|") && 
            l.Contains("Expected Message"));
    }
Farmhouse answered 3/3, 2022 at 15:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.