I want to create a unit test to ensure that a method is logging an error using xUnit and Moq. This code worked in ASP.NET Core 2.1:
//Arrange
var logger = new Mock<ILogger<MyMiddleware>>();
var httpContext = new DefaultHttpContext();
var middleware = new MyMiddleware(request => Task.FromResult(httpContext), logger.Object);
//Act
await middleware.InvokeAsync(httpContext);
//Assert
logger.Verify(x => x.Log(LogLevel.Error, It.IsAny<EventId>(), It.IsAny<FormattedLogValues>(), It.IsAny<Exception>(), It.IsAny<Func<object, Exception, string>>()), Times.Once);
To validate that _logger.LogError("Error message");
was called in middleware.InvokeAsync
.
However, in ASP.NET Core 3.0, I am unable to verify that the logger is being called. Microsoft.Extensions.Logging.Internal
can no longer be referenced, so FormattedLogValues
is unavailable.
I tried changing the Assert()
to use object
instead of FormattedLogValues
, and also IReadOnlyList<KeyValuePair<string, object>>
since that is what FormattedLogValues
is based on (FormattedLogValues.cs).
This is the error message I am getting in the Visual Studio test runner:
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: x => x.Log<object>(LogLevel.Error, It.IsAny<EventId>(), It.IsAny<object>(), It.IsAny<Exception>(), It.IsAny<Func<object, Exception, string>>())
Performed invocations:
ILogger.Log<FormattedLogValues>(LogLevel.Error, 0, Error message, null, Func<FormattedLogValues, Exception, string>)
Stack Trace:
Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)
Mock`1.Verify(Expression`1 expression, Times times)
Mock`1.Verify(Expression`1 expression, Func`1 times)
MyMiddlewareTests.InvokeAsync_ErrorIsLogged() line 35
--- End of stack trace from previous location where exception was thrown ---
How can I validate the error is being logged in ASP.NET Core 3.0?