Вы можете сделать что-то вроде этого
( примечание: это не работает в данном конкретном случае, потому что LogError
- это метод расширения, обновление см. Ниже ):
Mock<ILogger> _logger; // declare it somewhere where your test can access it
[Fact]
public void TestLogErrorMessage()
{
MyClass myClass = new MyClass(MockLoggerFactory().Object);
var result = myClass.Mymethod("a")
_logger.Verify();
}
private Mock<ILoggerFactory> MockLoggerFactory()
{
_logger = new Mock<ILogger>();
_logger.Setup(log => log.LogError(It.IsAny<string>())).Verifiable();
Mock<ILoggerFactory> mockLoggerFactory = new Mock<ILoggerFactory>(MockBehavior.Default);
mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>()))
.Returns(_logger.Object);
return mockLoggerFactory;
}
Ключевым моментом, на который следует обратить внимание, является вызов Verifiable()
после настройки макета ILogger
. Вы можете прочитать немного больше о Verifiable()
в этом ТАКОМ вопросе . После выполнения теста вы можете проверить, был ли вызван метод, вызвав .Verify()
на макете.
В зависимости от ваших потребностей, вы можете установить это в конструкторе вашего тестового класса (если он вам нужен)для всех / большинства тестов) или непосредственно внутри вашего метода тестирования. Вы также можете вернуть его вместе с ILoggerFactory
. Смысл в том, чтобы удерживать регистратор, чтобы вы могли проверить по нему, что метод был вызван.
В вашем конкретном случае (при попытке проверить вызовы ILogger.LogError
) вы не должны издеваться над LogError
, нобазовый метод ILogger.Log
. Это может выглядеть так:
var formatter = new Func<It.IsAnyType, Exception, string>((a, b) => "");
m.Setup(x => x.Log<It.IsAnyType>(LogLevel.Error,
It.IsAny<EventId>(),
It.IsAny<It.IsAnyType>(),
It.IsAny<Exception>(),
formatter))
.Verifiable();
Другая альтернатива - создать поддельную реализацию ILogger
и вернуть ее из Mock<ILoggerFactory>
:
mockLoggerFactory.Setup(_ => _.CreateLogger(It.IsAny<string>())
.Returns(new FakeLogger());
public class FakeLogger : ILogger
{
public static bool LogErrorCalled { get; set; }
public IDisposable BeginScope<TState>(TState state)
{
throw new NotImplementedException();
}
public bool IsEnabled(LogLevel logLevel) => true;
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{
if(logLevel == LogLevel.Error)
{
LogErrorCalled = true;
}
}
}
А затем после вашеготест вы можете проверить, является ли FakeLogger.LogErrorCalled
true
. Это упрощено для вашего конкретного теста - вы можете получить более сложный, чем это, конечно.