Dla każdego, która chciałaby odpowiedzieć na to pytanie, a nie jako pracę wokół, I przedłużony pracę tego artykułu:
https://ardalis.com/testing-logging-in-aspnet-core
Wrap jakakolwiek część ram rejestrowania, że używasz, co jest dobry pomysł. Start z własnym interfejsem logowania:
public interface ILog<T>
{
void LogError(Exception ex, string message, params object[] args);
void LogInformation(string message, params object[] args);
}
Następnie dodać realizację przekazać za pośrednictwem zaproszeń do ram:
public class Log<T> : ILog<T>
{
private readonly ILogger<T> logger;
public Log(ILogger<T> logger)
{
this.logger = logger;
}
public void LogError(Exception ex, string message, params object[] args) => this.logger.LogError(ex, message, args);
public void LogInformation(string message, params object[] args) => this.logger.LogInformation(message, args);
}
Idąc dalej, dodać interfejs do owijania fabrykę Rejestrator:
public interface ILogFactory
{
ILog<T> CreateLog<T>();
}
I realizacja:
public class LogFactory : ILogFactory
{
private readonly ILoggerFactory loggerFactory;
public LogFactory()
{
this.loggerFactory = new LoggerFactory();
}
public ILog<T> CreateLog<T>() => new Log<T>(new Logger<T>(this.loggerFactory));
}
Są to jedyne miejsca, w których należy odwoływać się do przestrzeni nazw Microsoft.Extensions.Logging
. W innym miejscu użyj numeru ILog<T>
zamiast ILogger<T>
i swojego ILogFactory
zamiast ILoggerFactory
. Gdzie normalnie można uzależnienie wstrzyknąć LoggerFactory
, zamiast wstrzykiwać opakowanie:
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ILogFactory>(new LogFactory());
w głównym kodu można pobrać tę LogFactory
i stworzyć swój specyficzny Log<T>
dla swojej klasy:
public class MyClass
{
public void MyMethod(IServiceCollection serviceCollection)
{
var serviceProvider = serviceCollection.BuildServiceProvider();
var logFactory = this.serviceProvider.GetRequiredService<ILogFactory>();
var log = logFactory.CreateLog<ServiceApplication>();
log.LogInformation("Hello, World!");
}
}
można sobie wyobrazić zmieniając parametr MyMethod
od IServiceCollection
do ILogFactory
lub ILog<MyClass>
zgodnie z wymaganiami. I - cały punkt jest - można teraz drwić powyższy kod z:
[Fact]
public void Test()
{
IServiceCollection serviceCollection = new ServiceCollection();
var mockLog = new Mock<ILog<MyClass>>();
var mockLogFactory = new Mock<ILogFactory>();
mockLogFactory.Setup(f => f.CreateLog<MyClass>()).Returns(mockLog.Object);
serviceCollection.AddSingleton<ILogFactory>(mockLogFactory.Object);
var myClass = new MyClass();
myClass.MyMethod(serviceCollection);
mockLog.Verify(l => l.LogInformation("Hello, World!"), Times.Once);
}
„W zależności od rodzaju, że nie kontrolują całej aplikacji dodaje sprzęgło i często staje się źródłem problemów i długu technicznego.” - Steve Smith
Zazwyczaj wprowadzamy sterownik "ILogger". Jaki jest powód wstrzyknięcia "ILoggerFactory"? –
Win
Mogę spróbować. Czy nadal nie będzie korzystać z metody rozszerzenia, a zatem nadal nie będzie działać? –
To działa! Jeśli zmienię wstrzyknięty obiekt na ILogger, mogę wyśmiać rejestrator za pomocą "var mockLogger = new Mock >();" a następnie przekazać mockLogger.Object do kontrolera testowego. Jeśli @Win opublikujesz odpowiedź, z przyjemnością ją zaakceptuję. –