Как проверить, что ошибка регистрируется в модульном тесте для ASP.NET Core 3.0? - PullRequest
1 голос
/ 09 октября 2019

Я хочу создать модульный тест, чтобы убедиться, что метод регистрирует ошибку, используя 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);

Чтобы проверить, что _logger.LogError("Error message"); был вызван в middleware.InvokeAsync.

Однако в ASP.NET Core 3.0 я не могучтобы убедиться, что регистратор вызывается. На Microsoft.Extensions.Logging.Internal больше нельзя ссылаться, поэтому FormattedLogValues недоступен.

Я попытался изменить утверждение, чтобы использовать object вместо 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 ---

Как проверитьрегистрируется ошибка в ASP.NET Core 3.0?

Ответы [ 2 ]

2 голосов
/ 09 октября 2019

Существует проблема на странице aspnet github по этому поводу. Кажется, проблема в Moq, и они внесли изменения, чтобы исправить это.

Вам нужно будет обновить до Moq 4.13, чтобы получить исправление.

Они ввели It.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);

Примечание: последний параметр должен быть приведен к типупоскольку Moq в настоящее время не поддерживает сопоставления вложенных типов.

Более подробную информацию о Moq можно найти здесь

0 голосов
/ 09 октября 2019

Я использую подход SGA (Setup, Grab, Assert).

//In the setup part
var mockLog = new Mock<ILogger>(MockBehavior.Strict);
string error = null;
mockLog.Setup(l => l
    .Error(It.IsAny<Exception>(), It.IsAny<string>()))
    .Callback((Exception b, string c) =>
    {
        error = c + " " + b.GetBaseException().Message;
        // This would keep only the last error, but it's OK, since there should be zero
        // Sometimes I use a collection and append the error info.
    });


//In the assert part
Assert.IsNull(error, $"Error detected: {error}");
...