Inizializza il log4net il prima possibile con NUnit
Domanda
Mi sto chiedendo qual è il modo migliore per inizializzare log4net in un progetto NUnit. Ovviamente voglio chiamare il codice iniziale (cioè XmlConfigurator.Configure()
) non appena possibile per ottenere il maggior numero possibile di registro. Ma dal momento che il mio progetto è gestito attraverso NULIT, ho un piccolo controllo sul suo punto di ingresso.
Secondo la documentazione NUnit, dovrebbe prima chiamare alcuni costruttori, quindi un metodo contrassegnato con l'attributo [SetUp]
in una classe contrassegnata con [TestFixtureSetup]
.
Allora, in primo luogo, ho creato una classe di aiutante statica che posso chiamare più volte senza problemi.
public static class LoggingFacility
{
private static bool _loggerIsUp = false;
public static void InitLogger()
{
if (_loggerIsUp == false)
XmlConfigurator.ConfigureAndWatch(f);
_loggerIsUp = true;
}
}
.
Allora, ho creato tutto il mio [TestFixtureSetup]
eredita un singolo che non fa praticamente nient'altro che chiamare LoggingFacility.initLogger()
. Ma che lascia ancora tutti i costruttori che vengono eseguiti in precedenza, in un ordine posso solo assumere casualmente. E inoltre, probabilmente farà alcune inizializzazioni statiche prima di essere persino in grado di eseguire un codice.
In effetti, come posso vedere nel mio registro, i primi 4 secondi o meno dell'esecuzione sono completamente non registrati.
Significa che dovrò chiamare il mio InitLogger()
in ogni costruttore e vietare l'uso di qualsiasi inizializzazione statica? Questo è un lavoro duro!
Qualcuno conosce un trucco magico con questo?
Soluzione 2
Un compagno di lavoro mi ha fornito il seguente funzionamento, che fa il lavoro:
In tutte le mie classi che richiedono la registrazione, ho avuto la seguente inizializzazione del logger
private static readonly ILog Log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
.
Lo ho semplicemente cambiato in un Iniziatore Singleton
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);
}
}
.
Poiché ho questo codice in ogni classe, questo inizializzazione statico deve essere chiamato molto presto da Nunit Wile istanziando le mie classi di prova.
Il passaggio successivo è quello di rendere tale discluso: (
Altri suggerimenti
Per un singolo punto di inizializzazione è necessario utilizzare la classe contrassegnata con [SetUpFixture]
Attributo e metodo contrassegnato con [SetUp]
, ad esempio:
[SetUpFixture]
public class TestsInitializer
{
[SetUp]
public void InitializeLogger()
{
LoggingFacility.InitLogger();
}
}
.
Ora, questo metodo ([SetUp] InitializeLogger
) eseguirà prima che qualsiasi test sia eseguito, come una marcata con [TearDown]
verrà eseguito una volta eseguito tutti i test. Ma ecco la cattura - cosa significa [SetUpFixture]
.
Ad esempio, assumendo la gerarchia come questa:
.
- Tests
--- Business
----- TestsInitializer.cs // SetUpFixture class
----- FirstBusinessTests.cs
----- SecondBusinesTests.cs
--- ComplexLogic
----- VeryComplexLogicTests.cs
First
e SecondBusinessTests
eseguiranno dopo SetUp
da TestsInitializer
, tuttavia VeryComplexLogicTests
potrebbe funzionare in ordine casuale.
Secondo Documentazione collegata , se dichiari la classe SetUpFixture
Qualsiasi spazio dei nomi, configurazione e degrado si applicherà per l'intero assembly:
.Solo una setupfixtura deve essere creata in un determinato spazio dei nomi. Una configurazione di setup al di fuori di qualsiasi spazio dei nomi fornisce la configurazione e il sapore per l'intero assembly.