【问题标题】:How to unit test a custom logger which is a wrapper around tracesource object如何对作为跟踪源对象的包装器的自定义记录器进行单元测试
【发布时间】:2016-03-14 02:46:28
【问题描述】:

我有一个 TraceSource 类的包装器。我想知道如何对它进行单元测试。由于我需要配置 app.config 文件以便将跟踪侦听器添加到 TraceSource 对象,添加 SwtichSource 等。那么在单元测试 dll 中手动添加 app.config 文件并将其配置为进行单元测试是否有效?我知道我们可以以编程方式完成所有这些,但是我在 TraceSource 周围创建一个包装器的方式看起来很棘手,或者可能是不可能的。任何建议都将受到欢迎。

public class Logger : ILogger
{

    private const int ERROR_EVENT_ID = 2;
    private const int DEBUG_EVENT_ID = 5;
    private  static TraceSource source;

    public Logger(string nameOfComponent)
    {
         source = new TraceSource(nameOfComponent);
    }

    public  void LogDebug(string message, string methodName)
    {
        if (string.IsNullOrEmpty(message) || string.IsNullOrEmpty(methodName))
            throw new ArgumentNullException("message, methodName can't be null or empty");

        source.TraceEvent(TraceEventType.Verbose, DEBUG_EVENT_ID);
    }

    public  void LogError(string methodName, Exception ex)
    {
        LogError(null, methodName, ex);
    }

    public  void LogError(string message, string methodName, Exception ex)           {
        if (String.IsNullOrEmpty(message) || String.IsNullOrEmpty(methodName) || ex == null)
            throw new ArgumentNullException("message, methodName and exception can't be null or empty");

        source.TraceData(TraceEventType.Error, ERROR_EVENT_ID, message, methodName, ex);
    }
  }

【问题讨论】:

    标签: c# unit-testing logging trace


    【解决方案1】:

    与其让此类为自己创建一个TraceSource,不如通过构造函数注入将TraceSource 注入其中。这样,在您的单元测试中,您可以使用侦听器初始化 TraceSource,让您记录对它所做的事情。

    您还应该确保您的 source 字段不是静态的,因为它被非静态构造函数初始化并被非静态方法使用。

    【讨论】:

    • 这有意义吗?
    • @StriplingWarrior 我应该去依赖注入将tracesource实例注入到Logger构造函数吗?
    • 依赖注入是否适用于多线程场景?
    • 重要的是每个访问 Logger 类的类都进行跟踪/记录。我需要那个类的名称,如果我通过依赖注入将跟踪源注入 Logger 类的构造函数,我不确定是否能够这样做?由于 TraceSource 构造函数将具有类的名称,例如 TraceSource source = new TraceSource("正在发生跟踪/记录的类的名称")。
    • @user2913184:你可以有两个构造函数:一个像我描述的那样,另一个说:public Logger(string nameOfComponent) : this(new TraceSource(nameOfComponent))。这样,您可以在需要时注入 TraceSource(例如用于单元测试),但仍然有一个易于使用的构造函数来初始化静态实例。
    【解决方案2】:

    既然您说单元测试,并且单元测试(与验收或集成测试相反)不应延伸到包括操作系统在内的外部组件,我假设您想要测试此类的逻辑但不是'对测试日志消息是否真正到达目的地(文件或数据库或云或其他任何东西)感兴趣。

    如果是这样,那么解决方案是将TradeSource 类包装在一个没有逻辑的非常薄的包装器中(因此不需要单元测试)。这将允许您轻松地注入它或使用工厂创建它、模拟它,从而对 Logger 类中的逻辑进行单元测试。像这样:

    public class TraceSourceLogTarget : ITraceSourceLogTarget
    {
        private TraceSource _traceSource = new TraceSource();
    
        ...
    
        public void TraceEvent(TraceEventType eventType, int eventId)
        {
            _traceSource.TraceEvent(eventType, eventId);
        }
    
        ...
    }
    

    我个人会制作一个更通用的接口(如ILogTarget),如果你改变主意并确保你没有与这个框架紧密耦合,但它可以由其他日志框架实现,这样就可以了。

    【讨论】:

    • 不,实际上我正在尝试测试类逻辑/功能以及将日志记录到 oracle 数据库。
    • @user2913184 那么这不是单元测试,而是集成或验收测试。 artofunittesting.com/definition-of-a-unit-test“在内存中运行(例如,没有 DB 或文件访问)”
    • 同意。这将是一个集成测试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-27
    • 1970-01-01
    • 2018-05-27
    • 1970-01-01
    • 1970-01-01
    • 2015-01-23
    相关资源
    最近更新 更多