Подтвердить что ты не робот

Java, Junit - Захват стандартного ввода/вывода для использования в unit test

Я пишу интеграционные тесты с помощью JUnit для автоматизации тестирования консольного приложения. Приложение является домашним заданием, но эта часть не является домашней работой. Я хочу, чтобы эти тесты были более эффективными - я не хочу возвращаться и проверять уже проверенные части приложения. (Стандартные причины использования модульных тестов)

Во всяком случае, я не могу найти статью или найти статью о захвате вывода, чтобы я мог сделать assertEquals на ней, и не предоставлял автоматический ввод. Меня не волнует, идет ли выход/вход в панель консоли/вывода. Мне нужно только выполнить тест и проверить вывод, что ожидается с учетом ввода.

У кого-нибудь есть статья или код, чтобы помочь с этим.

4b9b3361

Ответ 1

Используйте System.setOut()System.setErr()) для перенаправления вывода на произвольный поток печати - который может быть таким, который вы читаете от программного.

Например:

final ByteArrayOutputStream myOut = new ByteArrayOutputStream();
System.setOut(new PrintStream(myOut));

// test stuff here...

final String standardOutput = myOut.toString();

Ответ 2

Класс System имеет методы setIn(), setOut() и setErr(), которые позволяют вам устанавливать стандартные потоки ввода, вывода и ошибок, например. до ByteArrayOutputStream, который вы можете проверить по своему усмотрению.

Ответ 3

Вот решение вместо ByteArrayOutputStream. Это ничего не добавляет к идее System.setOut. Скорее, я хочу поделиться реализацией, которая лучше, чем захват всего в ByteArrayOutputStream. Я предпочитаю захватывать только выбранную информацию и позволять всем сообщениям журналов появляться в консоли, поскольку они регистрируются, а не захватывают все в balckbox (размера которого?) Для последующей обработки.

/**
 * Once started, std output is redirected to this thread. 
 * Thread redirects all data to the former system.out and
 * captures some strings.*/
static abstract class OutputCaputre extends Thread {

    // overrdie these methods for System.err
    PrintStream getDownstream() { return System.out;}
    void restoreDownstream() { System.setOut(downstream);}

    // will be called for every line in the log
    protected abstract void userFilter(String line);

    final PrintStream downstream;
    public final PipedInputStream pis;
    private final PipedOutputStream pos;
    OutputCaputre() throws IOException {
        downstream = getDownstream();

        pos = new PipedOutputStream();
        pis = new PipedInputStream(pos);
        System.setOut(new PrintStream(pos));

        start();
    }

    public void run() {
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(pis));

            // once output is resotred, we must terminate
            while (true) {
                String line = br.readLine();
                if (line == null) {
                    return;
                }
                downstream.println(line);
                userFilter(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void terminate() throws InterruptedException, IOException {
        restoreDownstream(); // switch back to std
        pos.close(); // there will be no more data - signal that
        join(); // and wait until capture completes
    }
};

Вот пример использования класса:

OutputCaputre outputCapture = new OutputCaputre() {
    protected void userFilter(String line) {
        downstream.println("Capture: " + line);
    }       
};
System.out.println("do you see me captured?");
// here is your test    
outputCapture.terminate(); // finally, stop capturing