【问题标题】:LibLog - Asserting calls to the loggerLibLog - 断言对记录器的调用
【发布时间】:2017-01-09 10:06:27
【问题描述】:

使用 LibLog 时,是否可以断言对记录器的调用?鉴于 wiki 列出了以下使用示例:

public class MyClass
{
    private static readonly ILog Logger = LogProvider.For<MyClass>(); 
}

这里的记录器是对消费者隐藏的实现细节,这是使用这个库的最大好处。这样库使用者就不必担心记录器是如何实例化的。查看这篇博文:

http://dhickey.ie/2015/06/capturing-log-output-in-tests-with-xunit2/

似乎添加了很多样板来捕获日志输出,我不完全确定该方法,因为它还在单元测试中使用了重定向的 Serilog 输出,考虑到库,这似乎很奇怪应该只依赖于日志抽象吗?

我目前能想到的唯一选择是:

注入记录器 - 这对于库的使用者来说可能很奇怪,然后每个库都会携带它自己的需要注入的 ILogger 定义,从而破坏了抽象的优势。

连接到真正的日志框架 - 为 LibLog 设置当前的 LogProvider 以使用 Log4Net 或类似的,然后以某种方式尝试将模拟/存根 Logger 注入 Log4Net,并通过代理断言调用。

任何相对简单的方法来断言对记录器的调用都会受到赞赏,但我怀疑并行测试执行会导致问题,即使可以在上述记录器上断言调用?

【问题讨论】:

  • 你需要什么来测试通话记录?通常不需要。
  • @Artiom 为什么不需要它?什么样的测试涵盖了日志记录?
  • 我的任何项目都没有这种需求。这就是我问的原因。

标签: c# unit-testing liblog


【解决方案1】:

在几乎所有记录器的记录配置中,您可以配置然后在记录失败时抛出异常。

来自 nlog 的样本

<nlog throwExceptions="true">
 ... your nlog config
</nlog>

但是在 LibLog 创建的抽象中,您失去了这些功能

【讨论】:

    【解决方案2】:

    我在项目中做了什么:

    我已经创建了我的 LoggerFactory。它公开了与 NLogger 相同的静态方法。

    public class LoggerFactory
    {
        private static ILoggerFactoryStrategy _loggerFactoryStrategy = new DummyLoggerFactoryStrategy();
    
        public static void Initialize(ILoggerFactoryStrategy loggerFactoryStrategy)
        {
            _loggerFactoryStrategy = loggerFactoryStrategy;
        }
    
        public ILogger GetLogger<T>()
        {
            return _loggerFactoryStrategy.GetLogger<T>();
        }
    
        ....
    }
    

    虚拟策略可以只写调试输出或什么都不做。另一种策略可能看起来像:

    public class LoggerFactoryStrategy : ILoggerFactoryStrategy
    {
        public ILogger GetLogger<T>()
        {
            //create LibLog instance instead with LogProvider.For<T>()
            var nlogger = LogManager.GetLogger(typeof(T).Name); //create instance of NLogger
            return new NLogLogger(nlogger);
        }
    }
    

    而 NlogLogger 包装器可能就像

    internal class NLogLogger : ILogger
    {
        private readonly Logger _logger;
    
        public NLogLogger(Logger logger)
        {
            _logger = logger;
        }
    
        public void Debug(string message)
        {
            _logger.Debug(message);
        }
    
        public void Warn(string message, params object[] args)
        {
            _logger.Warn(message, args);
        }
    
        public void Info(Exception exception)
        {
            _logger.Info(exception);
        }
    
        ......
    }
    

    当应用程序启动时,我用适当的策略初始化它,在后台使用 NLogger

    如果我想测试对记录器的调用,我可以使用模拟策略。 这种方法允许您在解决方案中删除对记录器库的引用,根项目除外,并允许您在将来需要时从一个切换到另一个。

    此外,这允许我们在 PCL 项目中使用 NLogger。

    【讨论】:

    • 我不确定这与 LibLog 和断言对记录器的调用有什么特别的关系?
    • @Mig 添加了一个示例
    猜你喜欢
    • 2016-06-22
    • 2010-12-22
    • 2023-03-05
    • 2014-04-12
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 2015-10-22
    相关资源
    最近更新 更多