446 Stimmen

JUnit-Test für System.out.println()

Ich muss JUnit-Tests für eine alte Anwendung schreiben, die schlecht entworfen ist und eine Menge Fehlermeldungen in die Standardausgabe schreibt. Wenn die getResponse(String request) Methode verhält sich korrekt und liefert eine XML-Antwort:

@BeforeClass
public static void setUpClass() throws Exception {
    Properties queries = loadPropertiesFile("requests.properties");
    Properties responses = loadPropertiesFile("responses.properties");
    instance = new ResponseGenerator(queries, responses);
}

@Test
public void testGetResponse() {
    String request = "<some>request</some>";
    String expResult = "<some>response</some>";
    String result = instance.getResponse(request);
    assertEquals(expResult, result);
}

Wenn er jedoch fehlerhaftes XML erhält oder die Anfrage nicht versteht, gibt er zurück null und schreibt einige Dinge in die Standardausgabe.

Gibt es eine Möglichkeit, die Konsolenausgabe in JUnit zu bestätigen? Um Fälle wie zu fangen:

System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());

12voto

Disper Punkte 695

Wenn Sie Spring Boot verwenden würden (Sie haben erwähnt, dass Sie mit einer alten Anwendung arbeiten, also wahrscheinlich nicht, aber es könnte für andere von Nutzen sein), dann könnten Sie org.springframework.boot.test.rule.OutputCapture auf folgende Weise:

@Rule
public OutputCapture outputCapture = new OutputCapture();

@Test
public void out() {
    System.out.print("hello");
    assertEquals(outputCapture.toString(), "hello");
}

9voto

mguymon Punkte 8826

Die Antwort von @dfa ist großartig, also bin ich noch einen Schritt weiter gegangen, um das Testen von Ausgabeblöcken zu ermöglichen.

Zuerst habe ich TestHelper mit einer Methode captureOutput die die lästige Klasse CaptureTest . Die captureOutput-Methode übernimmt die Aufgabe des Auf- und Abbaus der Ausgabeströme. Wenn die Implementierung von CaptureOutput 's test Methode aufgerufen wird, hat sie Zugriff auf die für den Testblock erzeugte Ausgabe.

Quelle für TestHelper:

public class TestHelper {

    public static void captureOutput( CaptureTest test ) throws Exception {
        ByteArrayOutputStream outContent = new ByteArrayOutputStream();
        ByteArrayOutputStream errContent = new ByteArrayOutputStream();

        System.setOut(new PrintStream(outContent));
        System.setErr(new PrintStream(errContent));

        test.test( outContent, errContent );

        System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out)));
        System.setErr(new PrintStream(new FileOutputStream(FileDescriptor.out)));

    }
}

abstract class CaptureTest {
    public abstract void test( ByteArrayOutputStream outContent, ByteArrayOutputStream errContent ) throws Exception;
}

Beachten Sie, dass TestHelper und CaptureTest in derselben Datei definiert sind.

Dann können Sie in Ihrem Test die statische captureOutput importieren. Hier ist ein Beispiel mit JUnit:

// imports for junit
import static package.to.TestHelper.*;

public class SimpleTest {

    @Test
    public void testOutput() throws Exception {

        captureOutput( new CaptureTest() {
            @Override
            public void test(ByteArrayOutputStream outContent, ByteArrayOutputStream errContent) throws Exception {

                // code that writes to System.out

                assertEquals( "the expected output\n", outContent.toString() );
            }
        });
}

8voto

Antônio Medeiros Punkte 2558

Basierend auf @dfa's Antwort et eine weitere Antwort, die zeigt, wie man System.in testet Ich möchte meine Lösung für die Eingabe eines Programms und die Prüfung seiner Ausgabe vorstellen.

Als Referenz verwende ich JUnit 4.12.

Nehmen wir an, wir haben ein Programm, das einfach die Eingabe zur Ausgabe repliziert:

import java.util.Scanner;

public class SimpleProgram {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print(scanner.next());
        scanner.close();
    }
}

Um dies zu testen, können wir die folgende Klasse verwenden:

import static org.junit.Assert.*;

import java.io.*;

import org.junit.*;

public class SimpleProgramTest {
    private final InputStream systemIn = System.in;
    private final PrintStream systemOut = System.out;

    private ByteArrayInputStream testIn;
    private ByteArrayOutputStream testOut;

    @Before
    public void setUpOutput() {
        testOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(testOut));
    }

    private void provideInput(String data) {
        testIn = new ByteArrayInputStream(data.getBytes());
        System.setIn(testIn);
    }

    private String getOutput() {
        return testOut.toString();
    }

    @After
    public void restoreSystemInputOutput() {
        System.setIn(systemIn);
        System.setOut(systemOut);
    }

    @Test
    public void testCase1() {
        final String testString = "Hello!";
        provideInput(testString);

        SimpleProgram.main(new String[0]);

        assertEquals(testString, getOutput());
    }
}

Ich werde nicht viel erklären, weil ich glaube, dass der Code lesbar ist und ich meine Quellen angegeben habe.

Wenn JUnit läuft testCase1() werden die Hilfsmethoden in der Reihenfolge aufgerufen, in der sie erscheinen:

  1. setUpOutput() wegen der @Before Anmerkung
  2. provideInput(String data) , aufgerufen von testCase1()
  3. getOutput() , aufgerufen von testCase1()
  4. restoreSystemInputOutput() wegen der @After Anmerkung

Ich habe nicht getestet System.err weil ich es nicht brauchte, aber es sollte einfach zu implementieren sein, ähnlich wie beim Testen System.out .

2voto

Jens Piegsa Punkte 7030

Vollständiges JUnit 5-Beispiel zum Testen System.out (ersetzen Sie den wenn-Teil):

package learning;

import static org.assertj.core.api.BDDAssertions.then;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

class SystemOutLT {

    private PrintStream originalSystemOut;
    private ByteArrayOutputStream systemOutContent;

    @BeforeEach
    void redirectSystemOutStream() {

        originalSystemOut = System.out;

        // given
        systemOutContent = new ByteArrayOutputStream();
        System.setOut(new PrintStream(systemOutContent));
    }

    @AfterEach
    void restoreSystemOutStream() {
        System.setOut(originalSystemOut);
    }

    @Test
    void shouldPrintToSystemOut() {

        // when
        System.out.println("example");

        then(systemOutContent.toString()).containsIgnoringCase("example");
    }
}

1voto

Shimon Doodkin Punkte 3946

Für aus

@Test
void it_prints_out() {

    PrintStream save_out=System.out;final ByteArrayOutputStream out = new ByteArrayOutputStream();System.setOut(new PrintStream(out));

    System.out.println("Hello World!");
    assertEquals("Hello World!\r\n", out.toString());

    System.setOut(save_out);
}

für Irrtum

@Test
void it_prints_err() {

    PrintStream save_err=System.err;final ByteArrayOutputStream err= new ByteArrayOutputStream();System.setErr(new PrintStream(err));

    System.err.println("Hello World!");
    assertEquals("Hello World!\r\n", err.toString());

    System.setErr(save_err);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X