TL;DR:
As mocking open generic types isn't possible with Moq, creating actual mock is inescapable. Here's the bare minimal mock I ended up using:
internal interface ILoggerMock {
public List<(LogLevel logLevel, string msg)> Logs { get; }
}
public class LoggerMock<T> : ILoggerMock, ILogger<T> {
public List<(LogLevel logLevel, string msg)> Logs { get; } = new();
public IDisposable BeginScope<TState>(TState state) => throw new NotImplementedException();
public bool IsEnabled(LogLevel logLevel) => throw new NotImplementedException();
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) {
var formattedLogMessage = formatter(state, exception);
Logs.Add((logLevel, formattedLogMessage));
}
}
With this registration:
var myServiceProvider = new ServiceCollection()
// ... more registrations as needed ...
.AddSingleton(typeof(ILogger<>), typeof(LoggerMock<>))
// ... more registrations as needed ...
.BuildServiceProvider()
_loggerMock = (ILoggerMock) myServiceProvider.GetService(typeof(ILogger<Answer>));
The original question:
Each class gets injected with ILogger<T>
where T
is each class, e.g.:
public class Question {
public Question(ILogger<Question> logger) { /* ... */ }
}
public class Answer {
public Answer(ILogger<Answer> logger) { /* ... */ }
}
But then it means that I must create a mock for each and every ILogger<T>
consumer:
var questionLoggerMock = new Mock<ILogger<Question>>();
var answerLoggerMock = new Mock<ILogger<Answer>>();
var services = new ServiceCollection()
.AddScoped<ILogger<Question>>(_ => questionLoggerMock.Object)
.AddScoped<ILogger<Answer>>(_ => answerLoggerMock.Object)
/*
.
... all other ILogger consumers...
.
*/
I tried many tricks, such as .AddSingleton<ILogger<object>>(_ => omniLoggerMock.Object)
or .AddSingleton(typeof(ILogger<>), _ => omniLoggerMock.Object)
, but none seem to work (if compiled, they fail in runtime).
Is there a simple solution to that, or am I doomed to create a new mock for each and every generic type?