How to test asp.net core built-in Ilogger

喜你入骨 提交于 2019-12-03 08:14:17

问题


I want to verify some logs logged. I am using the asp.net core built-in ILogger, and inject it with the asp.net core built-in DI:

private readonly ILogger<InvoiceApi> _logger;

public InvoiceApi(ILogger<InvoiceApi> logger)
{
    _logger = logger;
}

then I use it like: _logger.LogError("error));

I tried to mock it (with moq) as usual by:

MockLogger = new Mock<ILogger<InvoiceApi>>();

and inject this in the service for test by:

new InvoiceApi(MockLogger.Object);

then tried verify:

MockLogger.Verify(m => m.LogError(It.Is<string>(s => s.Contains("CreateInvoiceFailed"))));

but it throw:

Invalid verify on a non-virtual (overridable in VB) member: m => m.LogError

So, how can I verify this logs logged?


回答1:


As @Nkosi've already said, you can't mock an extension method. What you should mock, is the ILogger.Log method, which LogError calls into. It makes the verification code a bit clunky, but it should work:

MockLogger.Verify(
    m => m.Log(
        LogLevel.Error,
        It.IsAny<EventId>(),
        It.Is<FormattedLogValues>(v => v.ToString().Contains("CreateInvoiceFailed")),
        It.IsAny<Exception>(),
        It.IsAny<Func<object, Exception, string>>()
    )
);

(Not sure if this compiles, but you get the gist)




回答2:


I've written a short article showing a variety of approaches, including mocking the underlying Log() method as described in other answers here. The article includes a full GitHub repo with each of the different options. In the end, my recommendation is to use your own adapter rather than working directly with the ILogger type, if you need to be able to test that it's being called.

https://ardalis.com/testing-logging-in-aspnet-core




回答3:


LogError is an extension method (static) not an instance method. You can't "directly" mock static methods (hence extension method) with a mocking framework therefore Moq is unable to mock and hence verify that method. I have seen suggestions online about adapting/wrapping the target interface and doing your mocks on that but that would mean rewrites if you have used the default ILogger throughout your code in many places. You would have to create 2 new types, one for the wrapper class and the other for the mockable interface.



来源:https://stackoverflow.com/questions/39604198/how-to-test-asp-net-core-built-in-ilogger

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!