I'm trying to test that one of my controller end points calls the LogError once. This is the test:
[Fact]
public void Log_error_should_call_logger_error_method()
{
//Arrange
var applicationException = new ApplicationException("This is a mocked exception");
var exceptionHandlerFeatureMock = ErrorsControllerGenerator.GenerateExceptionHandlerFeatureMock(applicationException);
Mock<ILogger<ErrorsController>> iLoggerMock = new Mock<ILogger<ErrorsController>>();
var sut = ErrorsControllerGenerator.GenerateErrorsController(exceptionHandlerFeatureMock, iLoggerMock);
//Act
sut.LogError("This is a test error");
//Assert
iLoggerMock.Verify(x => x.LogError("This is a test error"), Times.Once());
}
I'm receiving the following error when running the test:
System.NotSupportedException : Invalid verify on a non-virtual (overridable in VB) member: x => x.LogError("This is a test error", new[] { })
I'm slightly confused by this as from what I understand, this shouldn't happen because I'm mocking the interface rather than the concrete implementation? If I was to use the concrete logger class, I know that the method would have to be marked as virtual for this to work but I didn't think that was the case when using interfaces.
I've tried adding this line to the //Arrange
part of the test:
iLoggerMock.Setup(x => x.LogError(It.IsAny<string>())).Verifiable();
But this just throws this error instead:
System.NotSupportedException : Expression references a method that does not belong to the mocked object: x => x.LogError(It.IsAny<String>(), new[] { })
This also confuses me as the mocked object (ILogger
) does have a LogError
method
CodePudding user response:
You can't mock logger methods such as LogError
because unfortunately they are extension methods and are not defined in the ILogger
interface.
Instead of trying to verify whether the relevant log methods were called, perhaps you could verify the executed code takes the expected path i.e. the path where the relevant log methods would be called.