Инициализируйте log4Net как можно раньше с помощью NUnit
Вопрос
Мне интересно, как лучше всего инициализировать log4Net в проекте NUnit.Конечно, я хочу вызвать код инициализации (т.е. XmlConfigurator.Configure()
) как можно скорее получить как можно больше ранних выходных данных журнала.Но поскольку мой проект запускается через NUnit, я практически не контролирую его точку входа.
Согласно документации NUnit, сначала он должен вызвать некоторые конструкторы, затем метод, помеченный [SetUp]
атрибут в классе, помеченный знаком [TestFixtureSetup]
.
Итак, во-первых, я создал статический вспомогательный класс, который я могу вызывать несколько раз без проблем.
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()
в каждом конструкторе и запретить использование любого статического инициализатора?Это тяжелая работа!
Кто-нибудь знает волшебный трюк с этим?
Решение 2
Работа Mate предоставила мне следующий обходной путь, что делает работу:
Во всех моих классах, которые требуют регистрации, у меня был следующий инициализация регистратора регистратора
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 Wile.
Следующий шаг - сделать эту резьбу безопасностью: (
Другие советы
Для единственной точки инициализации вы должны использовать класс, помеченный знаком [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
First
и SecondBusinessTests
будет работать после SetUp
От TestsInitializer
, однако VeryComplexLogicTests
может выполняться в случайном порядке.
Согласно связанная документация, если вы заявите SetUpFixture
класс вне любого пространства имен, настройка и демонтаж будут применяться ко всей сборке:
В данном пространстве имен должна быть создана только одна SetUpFixture.SetUpFixture вне любого пространства имен обеспечивает настройку и демонтаж для всей сборки.