Đối với bất cứ ai cần một câu trả lời cho câu hỏi này, chứ không phải là một công việc xung quanh, tôi đã mở rộng công việc của bài viết này:
https://ardalis.com/testing-logging-in-aspnet-core
Bọc bất kỳ một phần của khung đăng nhập mà bạn sử dụng, đó là một ý tưởng hay. Bắt đầu với giao diện đăng nhập của riêng bạn:
public interface ILog<T>
{
void LogError(Exception ex, string message, params object[] args);
void LogInformation(string message, params object[] args);
}
Sau đó thêm việc thực hiện để vượt qua thông qua các cuộc gọi đến khuôn khổ:
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);
}
Di chuyển trên, thêm một giao diện cho gói nhà máy logger:
public interface ILogFactory
{
ILog<T> CreateLog<T>();
}
Và triển khai:
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));
}
Đây là những nơi duy nhất bạn nên tham khảo không gian tên Microsoft.Extensions.Logging
. Ở những nơi khác, hãy sử dụng ILog<T>
thay vì ILogger<T>
và ILogFactory
thay vì ILoggerFactory
của bạn. Nơi bạn sẽ thường phụ thuộc tiêm LoggerFactory
, thay vì tiêm wrapper:
IServiceCollection serviceCollection = new ServiceCollection();
serviceCollection.AddSingleton<ILogFactory>(new LogFactory());
Trong mã chính của bạn, bạn có thể lấy LogFactory
này và tạo cụ thể Log<T>
của bạn cho lớp học của bạn:
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!");
}
}
Bạn có thể tưởng tượng thay đổi thông số của MyMethod
từ IServiceCollection
đến ILogFactory
hoặc ILog<MyClass>
theo yêu cầu. Và - toàn bộ vấn đề là - bây giờ bạn có thể thử các mã trên với:
[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);
}
"Tùy thuộc vào loại bạn không kiểm soát suốt ứng dụng của bạn thêm khớp nối và thường xuyên trở thành một nguồn của vấn đề và nợ kỹ thuật." - Steve Smith
Chúng tôi thường tiêm 'ILogger' vào bộ điều khiển. Lý do đằng sau việc tiêm 'ILoggerFactory' là gì? –
Win
Tôi có thể thử. Nó sẽ không còn sử dụng phương pháp mở rộng và do đó vẫn thất bại? –
Nó hoạt động! Nếu tôi thay đổi đối tượng được tiêm vào ILogger, tôi có thể giả lập trình ghi với "var mockLogger = new Mock >();" và sau đó vượt qua mockLogger.Object vào bộ điều khiển thử nghiệm. Nếu bạn @Win đăng câu trả lời, tôi sẽ rất vui khi được chấp nhận. –