如何检查 ASP.NET Core 3.0 的单元测试中是否记录了错误?

brl*_*brl 3 c# moq xunit.net asp.net-core asp.net-core-3.0

我想创建一个单元测试以确保方法使用 xUnit 和 Moq 记录错误。此代码适用于 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);
Run Code Online (Sandbox Code Playgroud)

为了验证_logger.LogError("Error message");在middleware.InvokeAsync.

但是,在 ASP.NET Core 3.0 中,我无法验证是否正在调用记录器。Microsoft.Extensions.Logging.Internal不能再引用,所以FormattedLogValues不可用。

我尝试更改Assert()to useobject而不是FormattedLogValues,而且IReadOnlyList<KeyValuePair<string, object>>因为那FormattedLogValues是基于(FormattedLogValues.cs)。

这是我在 Visual Studio 测试运行程序中收到的错误消息:

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 ---
Run Code Online (Sandbox Code Playgroud)

如何验证错误是否记录在 ASP.NET Core 3.0 中?

Sim*_*Ged 6

aspnet github 页面上有一个关于此的问题。似乎问题出在Moq,他们已经进行了更改以修复它。

您将需要升级到Moq 4.13以获得修复。

他们引入了 anIt.IsAnyType来解决内部对象的问题,因此您应该能够像这样更改object引用It.IsAnyType并编写测试:

logger.Verify(x => x.Log(LogLevel.Error, It.IsAny<EventId>(), It.IsAny<It.IsAnyType>(), It.IsAny<Exception>(), (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()), Times.Once);
Run Code Online (Sandbox Code Playgroud)

注意:最后一个参数需要进行类型转换,因为Moq当前不支持嵌套类型匹配器。

Moq可以在此处找到更多详细信息