Frage

Ich frage mich, wie man log4Net in einem NUnit-Projekt am besten initialisiert.Natürlich möchte ich den Init-Code aufrufen (d. h. XmlConfigurator.Configure()) so schnell wie möglich, um so viele frühe Protokollausgaben wie möglich zu erhalten.Da mein Projekt jedoch über NUnit ausgeführt wird, habe ich kaum Kontrolle über den Einstiegspunkt.

Laut NUnit-Dokumentation sollten zuerst einige Konstruktoren und dann eine mit dem markierte Methode aufgerufen werden [SetUp] Attribut in einer mit markierten Klasse [TestFixtureSetup].

Also habe ich zunächst eine statische Hilfsklasse erstellt, die ich problemlos mehrmals aufrufen kann.

  public static class LoggingFacility
  {
    private static bool _loggerIsUp = false;

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

      _loggerIsUp = true;
    }
  }

Dann habe ich alles gemacht [TestFixtureSetup] einen einzigen erben, der so gut wie nichts anderes tut als anzurufen LoggingFacility.initLogger().Damit bleiben aber immer noch alle Konstruktoren übrig, die früher ausgeführt werden, und zwar in einer Reihenfolge, von der ich nur annehmen kann, dass sie zufällig ist.Und außerdem werden wahrscheinlich einige statische Initialisierungen durchgeführt, bevor ich überhaupt Code ausführen kann.

Wie ich in meinem Protokoll sehen kann, werden die ersten etwa vier Sekunden der Ausführung tatsächlich überhaupt nicht aufgezeichnet.

Bedeutet das, dass ich meine anrufen muss? InitLogger() in jedem Konstruktor und die Verwendung eines statischen Initialisierers verbieten?Das ist harte Arbeit!

Kennt jemand einen Zaubertrick damit?

War es hilfreich?

Lösung 2

Ein Arbeitskollege hat mir den folgenden Workaround zur Verfügung gestellt, der funktioniert:

In allen meinen Klassen, die eine Protokollierung erfordern, hatte ich die folgende Logger-Initialisierung

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

Ich habe es einfach in einen Singleton-Initialisierer geändert

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);
  }
}

Da ich diesen Code in jeder Klasse habe, muss dieser statische Initialisierer sehr früh von NUnit aufgerufen werden, während meine Testklassen instanziiert werden.

Der nächste Schritt besteht darin, diesen Thread sicher zu machen :(

Andere Tipps

Für einen einzelnen Initialisierungspunkt sollten Sie eine mit markierte Klasse verwenden [SetUpFixture] Attribut und Methode markiert mit [SetUp], Zum Beispiel:

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

Nun ist diese Methode ([SetUp] InitializeLogger) werde rennen vor jedem Test ausgeführt wird, genauso wie die mit markierte [TearDown] wird ausgeführt, sobald alle Tests ausgeführt wurden.Aber hier ist der Haken: Was bedeutet das? beliebig Und alle in diesem Zusammenhang bedeuten?Tests aus Klassen im selben Namensraum deklariert wie die mit markierte Klasse [SetUpFixture].

Nehmen wir zum Beispiel eine Hierarchie wie diese:

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

First Und SecondBusinessTests werde rennen nach SetUp aus TestsInitializer, Jedoch VeryComplexLogicTests könnte in zufälliger Reihenfolge ausgeführt werden.

Entsprechend verlinkte Dokumentation, wenn Sie erklären SetUpFixture Wenn eine Klasse außerhalb eines Namensraums liegt, gelten Setup und Teardown für die gesamte Assembly:

In einem bestimmten Namespace sollte nur eine SetUpFixture erstellt werden.Ein SetUpFixture außerhalb eines Namensraums stellt SetUp und TearDown für die gesamte Baugruppe bereit.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top