Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock Microsoft.Extensions.Logging using Moq

I'm currently trying to get the following code to succeed at runtime:

public delegate void LogDelegate(LogLevel logLevel, EventId eventId, object state, Exception exception, Func<object, Exception, string> formatter);

public abstract class LoggingTestBase
{
    private Mock<ILogger> _mockLogger;

    public ILogger Setup(LogDelegate logCallback)
    {
        _mockLogger = new Mock<ILogger>(MockBehavior.Strict);
        _mockLogger.Setup(logger => logger.Log(
                It.IsAny<LogLevel>(),
                It.IsAny<EventId>(),
                It.IsAny<object>(),
                It.IsAny<Exception>(),
                It.IsAny<Func<object, Exception, string>>()))
            .Callback(logCallback);
        return _mockLogger.Object;
    }
}

The problem is, that I get a MockException once I run the test because the method that gets called is the generic ILogger.Log<FormattedLogValues>(...) which I obviously didn't setup.

Reading the existing answer to this and the Moq documentation I came to the conclusion that I should probably just mock the generic method with the correct type argument as shown above.

Here I stumbled into the next problem which brings me to the end of ideas:

In current versions of Microsoft.Extensions.Logging FormattedLogValues is no longer public but internal (following this PR) which makes impossible to mock the generic method that gets called in the end.

Has anyone successfully solved this issue? How?

like image 879
Brar Avatar asked Nov 06 '22 19:11

Brar


1 Answers

I have a similar issue. I just want to verify that a call to LogInformation is called. According to this -> https://github.com/aspnet/Extensions/issues/1319 It should probably be solved by Moq..

However, at the end there is an suggestion that you could use It.IsAnyType instead of object.. For you this would be something like:

_mockLogger.Setup(logger => logger.Log(
            It.IsAny<LogLevel>(),
            It.IsAny<EventId>(),
            It.IsAny<It.IsAnyType>(),
            It.IsAny<Exception>(),
            (Func<It.IsAnyType, Exception, string>) It.IsAny<object>()))
        .Callback(logCallback);

I've not been able to make it work, but maybe this pushes you in the right direction?

like image 140
Zaphod Avatar answered Nov 12 '22 14:11

Zaphod