2016-10-05 2 views
0

Ich habe zu schreiben habe eine OutputStream Klasse (inspiriert von this), die anstelle von stdout zu einem Logger schreibt zu schaffen, so kam ich mit dem Follow-up:Wie Unit-Test (e) für benutzerdefinierten Output

case class OutputStreamLogger(level: Level) extends OutputStream { 
    val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger") 
    private var mem = "" 

    /** 
     * Writes byte to Logger, flushes automatically at EOL 
     * 
     * @param b Int Int representation of character to get written 
     * 
     * @return Unit 
     */ 
    def write(b: Int): Unit = { 
     // To prevent internal conversion from byte to int 
     val bytes = new Array[Byte](1) 
     // Get least significant byte from int argument 
     bytes(0) = (b & 0xff).toByte 
     // Turn byte array into String 
     mem += new String(bytes) 

     // Automatically flush at EOL 
     if(mem.endsWith("\n")) { 
      // Grab everything but newline 
      mem = mem.substring(0, mem.length - 1) 
      // Log it 
      flush() 
     } 
    } 

    /** 
     * Sends output bytes to logger at specified level 
     * 
     * @return Unit 
     */ 
    override def flush(): Unit = { 
     level match { 
      // Passing the format then the String eliminates 
      // need to check if logging at that level is enabled 
      case Level.TRACE => logger.trace("{}", mem) 
      case Level.DEBUG => logger.debug("{}", mem) 
      case Level.INFO => logger.info("{}", mem) 
      case Level.WARN => logger.warn("{}", mem) 
      case Level.ERROR => logger.error("{}", mem) 
     } 
     // Clear out buffer 
     mem = "" 
    } 
} 

Wie würde ich dies testen? Ich habe bei anderen Beispielen für Unit-Tests OutputStream s gesucht, aber sie alle PrintStream verwenden, wo ich möchte meine OutputStreamLogger verwenden und scheinen nicht die

Antwort

1

Der Haupt Testbarkeit Problem mit Ihrer Ausgabe write und flush Methoden testen werden Strom ist wahrscheinlich diese Erklärung:

val logger: Logger = org.slf4j.LoggerFactory.getLogger("OutputStreamLogger") 

Sie haben den Logger bis auf eine konkrete Instanz genagelt, wo die Initialisierung dieser Instanz nicht angepasst werden kann. Sie können jetzt entweder eine slf4j-Protokollierungskonfiguration während des Komponententests verwenden, die in eine temporäre Datei schreibt und diese zurücklesen. Vielleicht gibt es auch einen benutzerdefinierten Appender, der in einen Zwischenspeicher schreibt.

Die andere Möglichkeit besteht darin, diese Deklaration zu ändern und bei der Instanzerstellung eine Logger-Spezifikation zuzulassen. Sie können dies verwenden, um einen Mock-Logger zu injizieren.

Testen würde dann nur etwas in den Ausgabestrom schreiben und sehen, ob ein Newline die Ausgabe an den Logger spült.

BTW - Ihre Implementierung sieht sehr ineffizient, da es eine neue Zeichenfolge für jedes geschriebene Byte erstellt. Und eine lokale Variable und ein Mitglied mit dem gleichen Namen zu haben, ist ebenfalls verwirrend.

+0

Die lokale Variable für 'mem' sollte nicht da sein und ich werde das Byte-Schreiben reparieren, damit es nicht so janky ist :) Die Freigabe des Loggers war definitiv hilfreich. Danke für die Vereinfachung und Hinweise! –