web-dev-qa-db-ja.com

Java、Junit-ユニットテストで使用する標準入力/出力をキャプチャします

JUnitを使用して、コンソールベースのアプリケーションのテストを自動化する統合テストを作成しています。アプリケーションは宿題ですが、この部分は宿題ではありません。これらのテストを自動化して生産性を高めたいのですが、戻ってアプリケーションの既にテスト済みの部分を再テストする必要はありません。 (単体テストを使用する標準的な理由)

とにかく、出力のキャプチャに関する記事を見つけられないため、assertEqualsを実行したり、自動入力を提供したりできません。出力/入力がコンソール/出力ペインに行くかどうかは気にしません。テストを実行して、出力が入力に対して予期されるものであることを確認するだけで済みます。

誰でもこれを手助けする記事やコードを持っています。

28
Frank V

System.setOut() (およびSystem.setErr())を使用して、出力を任意のprintstreamにリダイレクトします。これは、プログラムから読み取ることができます。

例えば:

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

// test stuff here...

final String standardOutput = myOut.toString();
46
Andrzej Doyle

Systemクラスには、setIn()setOut()およびsetErr()というメソッドがあり、標準入力、出力、エラーストリームを設定できます。あなたが自由に検査できるByteArrayOutputStreamに。

7

これが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
2
Val