使用 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]
的方法相同,将在所有测试运行后运行。但这里有一个问题 - any 和 all 在这种情况下是什么意思?来自与标有[SetUpFixture]
的类在同一命名空间中声明的类的测试。
例如,假设这样的层次结构:
- Tests
--- Business
----- TestsInitializer.cs // SetUpFixture class
----- FirstBusinessTests.cs
----- SecondBusinesTests.cs
--- ComplexLogic
----- VeryComplexLogicTests.cs
First
和 SecondBusinessTests
将从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的主要内容,如果未能解决你的问题,请参考以下文章