2012-03-07 72 views
2

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

根据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()并禁止使用任何静态初始化方法?这是一项艰巨的工作!

有人知道这个魔术吗?

+1

只是想为其目的,您正在使用log4net的在测试中,记录测试进度/结果或实例化一个记录器的一些类的依赖 – sll 2012-03-07 21:22:10

+0

@sll?我使用两个日志记录输出:第一个是测试输出比NUnit本身更详细,第二个(我需要快速准备的)用于调试测试应用程序 – PPC 2012-03-08 14:16:53

回答

1

一个工作伙伴给我提供了以下解决方法,那这项工作:

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

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会很早地调用我的测试类实例化。

下一步是使线程安全:(

4

对于单初始点,你应该使用标有[SetUpFixture]属性和方法打上[SetUp]类,例如:

[SetUpFixture] 
public class TestsInitializer 
{ 
    [SetUp] 
    public void InitializeLogger() 
    { 
     LoggingFacility.InitLogger(); 
    } 
} 

现在,这种方法([SetUp] InitializeLogger)将任何测试之前运行运行,同如所有标有[TearDown]的标签都将在所有测试运行后运行。但是,这里有什么呢?任何全部是什么意思?来自类的测试在与[SetUpFixture]标记的类相同的名称空间中声明。

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

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

FirstSecondBusinessTests会后SetUpTestsInitializer运行,但是VeryComplexLogicTests可能会以随机顺序运行。

linked documentation,如果声明SetUpFixture类中的任何命名空间,设置之外,并拆除将适用于整个组件:

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

+0

感谢命名空间提示,不过,我的问题是,NUnit在运行之前会运行很多代码*甚至想知道[SetUpFixture]:构造函数和静态初始化函数,我也想记录这些代码 – PPC 2012-03-08 14:14:50

+0

@PPC:运行什么样的代码*之前*?你的意思是NUnit的初始化或你的代码,像测试类构造函数等?我很肯定'SetUpFixture'只要将你的自定义代码连接到NUnit就行了。 *也许*你可以使用配置文件工作,但说实话,我从来没有见过任何人做过这样的事情。 – 2012-03-08 23:12:56

+0

是的,我的意思是构造函数等。我的第一个日志条目在大约5秒的正常运行时间开始,我没有看到我的大部分构造函数都在那里登录。 – PPC 2012-03-12 14:31:33