使用 NUnit 尽早初始化 log4Net

Posted

技术标签:

【中文标题】使用 NUnit 尽早初始化 log4Net【英文标题】:Initialize log4Net as early as possible with NUnit 【发布时间】:2012-03-07 20:36:28 【问题描述】:

我想知道在 NUnit 项目中初始化 log4Net 的最佳方法是什么。当然,我想尽快调用初始化代码(即XmlConfigurator.Configure())以获得尽可能多的早期日志输出。但是由于我的项目是通过 NUnit 运行的,所以我几乎无法控制它的入口点。

根据 NUnit 文档,它应该首先调用一些构造函数,然后在标有 [TestFixtureSetup] 的类中调用标有 [SetUp] 属性的方法。

所以,首先,我创建了一个静态助手类,我可以毫无问题地多次调用它。

  public static class LoggingFacility
  
    private static bool _loggerIsUp = false;

    public static void InitLogger()
    
      if (_loggerIsUp == false)
        XmlConfigurator.ConfigureAndWatch(f);

      _loggerIsUp = true;
    
  

然后,我让我所有的[TestFixtureSetup] 都继承了一个,除了调用LoggingFacility.initLogger() 之外几乎什么都不做。但这仍然留下了之前运行的所有构造函数,我只能假设随机的顺序。而且,它可能会在我能够执行一些代码之前进行一些静态初始化。

事实上,正如我在日志中看到的那样,执行的前 4 秒左右完全没有记录。

这是否意味着我必须在每个构造函数中调用我的InitLogger() 并禁止使用任何静态初始化程序?这是一项艰巨的工作!

有人知道这个魔术吗?

【问题讨论】:

只是想知道您在测试中使用 log4net 的目的是什么,记录测试进度/结果或将记录器实例化为某些类的依赖项? @sll:我使用两个日志输出:第一个用于测试输出比 NUnit 本身更详细一点,第二个(我需要快速准备好)用于调试测试应用 【参考方案1】:

对于单个初始化点,您应该使用标有[SetUpFixture] 属性的类和标有[SetUp] 的方法,例如:

[SetUpFixture]
public class TestsInitializer

    [SetUp]
    public void InitializeLogger()
    
        LoggingFacility.InitLogger();
    

现在,此方法 ([SetUp] InitializeLogger) 将在运行任何测试之前运行,与标记为 [TearDown] 的方法相同,将在所有测试运行后运行。但这里有一个问题 - anyall 在这种情况下是什么意思?来自与标有[SetUpFixture]的类在同一命名空间中声明的类的测试。

例如,假设这样的层次结构:

- Tests
--- Business
----- TestsInitializer.cs // SetUpFixture class
----- FirstBusinessTests.cs
----- SecondBusinesTests.cs
--- ComplexLogic
----- VeryComplexLogicTests.cs

FirstSecondBusinessTests 将从TestsInitializer 运行之后 SetUp,但是VeryComplexLogicTests 可能会以随机顺序运行。

根据linked documentation,如果您在任何命名空间之外声明SetUpFixture 类,则设置和拆卸将适用于整个程序集:

在给定的命名空间中只能创建一个 SetUpFixture。任何命名空间之外的 SetUpFixture 为整个程序集提供 SetUp 和 TearDown。

【讨论】:

感谢命名空间提示,非常感谢。尽管如此,我的问题是 NUnit 之前运行了大量代码,甚至想知道 [SetUpFixture]:构造函数和静态初始化器,我也想记录这段代码 @PPC:之前运行了什么样的代码?您的意思是 NUnit 的初始化或您的代码,例如测试类构造函数等?我很确定SetUpFixture 会尽快将您的自定义代码连接到 NUnit。 也许您可以使用配置文件按自己的方式工作,但老实说,我以前从未见过有人这样做。 是的,我的意思是构造函数等。我的第一个日志记录条目从正常运行时间大约 5 秒开始,我没有看到我的大多数构造函数在那里登录。【参考方案2】:

一位同事向我提供了以下解决方法,可以完成工作:

在我所有需要记录的类中,我进行了以下记录器初始化

private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

我只是把它改成了单例初始化器

private static readonly ILog Log = LoggingFacility.GetLoggerWithInit(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

/*** ... ***/

public static class LoggingFacility

  private static bool _loggerIsUp = false;

  public static ILog GetLoggerWithInit(Type declaringType)
  
    if (_loggerIsUp == false)
      XmlConfigurator.Configure(_log4NetCfgFile);
    _loggerIsUp = true;
    return LogManager.GetLogger(declaringType);
  

因为我在每个类中都有这段代码,所以 NUnit 在实例化我的测试类时必须很早就调用这个静态初始化程序。

下一步是使该线程安全:(

【讨论】:

以上是关于使用 NUnit 尽早初始化 log4Net的主要内容,如果未能解决你的问题,请参考以下文章

log4net配置与初始化

log4net 消息文本问题

如何为 WCF 配置 log4net

Log4net 集成到MVC+EF框架

log4使用介绍

为 .Net 单元测试设置 HttpContext