LoginSignup
7
11

More than 5 years have passed since last update.

Java コンソール出力(標準出力・標準エラー出力)内容をString文字列として取り出す

Last updated at Posted at 2015-10-24

標準出力・標準エラー出力の出力先をコンソールからオブジェクト内に変更する。
コンソール出力内容をテストしたい場合に使用する。

ConsoleSnatcher.java
package testlib.system;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

/**
 * 標準出力・標準エラー出力の出力先をコンソールから変更するクラス.くbr>
 * コンソール出力内容をテストしたい場合に使用する。<br>
 * 本クラスはスレッドセーフではないのでマルチスレッド環境では利用不可。くbr>
 * シングルトンクラス。<br>
 * log4jの出力内容を取得する場合はConsoleAppenderで、標準出力する。
 *
 * @author boss_ape
 */
public final class ConsoleSnatcher
{
    /** シングルトンパターンのためのインスタンス. */
    private static final ConsoleSnatcher INSTANCE = new ConsoleSnatcher();

    /** 変更前の標準出力. */
    private PrintStream nativeOut = null;

    /** 元の標準エラー出力. */
    private PrintStream nativeErr = null;

    /** 変更後の標準出力. */
    private ByteArrayOutputStream snatchedOut = new ByteArrayOutputStream();

    /** 変更後の標準エラー出力. */
    private ByteArrayOutputStream snatchedErr = new ByteArrayOutputStream();

    /** 出力先変更済みフラグ. */
    private boolean stealFlag = false;

    /**
     * デフォルトコンストラクタの禁止.
     */
    private ConsoleSnatcher() { }

    /**
     * このクラスのインスタンスを取得
     *
     * @return このクラスのインスタンス
     */
    public static ConsoleSnatcher getlnstance()
    {
        return INSTANCE;
    }

    /**
     * 出力先をコンソールからこのクラスへ出力するように変更する.
     */
    public void snatch()
    {
        // 2回以上の変更禁止
        if (!stealFlag) {
            // 現在の出力先の保存
            nativeOut = System.out;
            nativeErr = System.err;

            // 出力先変更
            System.setOut(new PrintStream(new BufferedOutputStream(snatchedOut)));
            System.setErr(new PrintStream(new BufferedOutputStream(snatchedErr)));

            //変更済みフラグ設定
            stealFlag = true;
        }
    }

    /**
     * 標準出力のクリア.
     */
    public void clearOutput()
    {
        snatchedOut.reset();
    }

    /**
     * 標準エラー出力のクリア.
     */
    public void clearErrorOutput()
    {
        snatchedErr.reset();
    }

    /**
     * 標準出力内容の取得.
     *
     * @return 標準出力内容
     */
    public String getOutput()
    {
        System.out.flush();
        return snatchedOut.toString();
    }

    /**
     * 標準エラー出力内容の取得.
     *
     * @return標準エラー出力内容
     */
    public String getErrorOutput()
    {
        System.err.flush();
        return snatchedErr.toString();
    }

    /**
     * 元の標準出力先の取得.
     *
     * @return 元の標準出力先
     */
    public PrintStream getNativeOutputStream()
    {
        return nativeOut;
    }

    /**
     * 元の標準エラー出力先の取得.
     *
     * @return 奪取した標準エラー出力先
     */
    public PrintStream getNativeErrorOutputStream()
    {
        return nativeErr;
    }

    /**
     * 出力先を元に戻すくbr>
     * 使用後は必ずこのメソッドを呼び出す。
     */
    public void release()
    {
        // 出力先が変更されている場合のみ実施
        if (stealFlag) {
            clearOutput();
            clearErrorOutput();

            //出力先を元に戻す
            System.setOut(nativeOut);
            System.setErr(nativeErr);

            stealFlag = false;
        }
    }
}

以下、使用サンプル。
まずはコンソール出力するJavaサンプル

SampleConsoleOutput.java
package jp.co.ivynetwork.batch;

/**
 * 標準出力と標準エラー出力するサンプル処理.<br>
 * 0:正常終了<br>
 * 1:異常終了
 *
 * @author boss_ape
 */
public class SampleConsoleOutput
{
    /**
     * fugafugaをhogehogeする
     *
     * @param args パラメータnullではない事
     */
    public static void hogeHoge(String arg)
    {
        try {
            // パラメータがnullならException発生
            if (null == arg)
                throw new NullPointerException();

        } catch (NullPointerException e) {
            // 標準エラー出力
            System.err.print("エラーが発生");
            return;
        }

        // 標準出力
        System.out.print("正常終了");
        return;
    }
}

上記クラスのJUnitテスト

SampleConsoleOutputTest.java
package jp.co.ivynetwork.batch;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import testlib.system.ConsoleSnatcher;

/**
 * SampleConsoleOutputクラステスト.<br>
 *
 * @author boss_ape
 */
public class SampleConsoleOutputTest
{
    /** 標準出力・標準エラー出力変更管理オブジェクト. */
    private ConsoleSnatcher stdout = ConsoleSnatcher.getlnstance();

    /**
     * テストメソッド実行前にSystem.exit()設定を変更.
     */
    @Before
    public void changeSystem()
    {
        // 標準出力・標準エラー出力先を変更
        stdout.snatch();
    }

    /**
     * 標準出力・標準エラー出力先設定を戻す.<br>
     * バッファにたまっていた内容を最後にコンソール出力する。
     */
    @After
    public void resetSystem()
    {
        // バッファにたまっている内容を一時退避
        String std = stdout.getOutput();
        String std_err = stdout.getErrorOutput();

        // コンソール出力に戻す
        stdout.release();

        // コンソール出力
        if (std.length() > 0) {
            System.out.println(System.getProperty("line.separator") + "--------");
            System.out.println(std);
        }
        if (std_err.length() > 0) {
            System.out.println(System.getProperty("line.separator") + "--------");
            System.out.println(std_err);
        }
    }

    /**
     * hogeHogeメソッド正常系のテスト.
     */
    @Test
    public void testHogeHoge正しいパラメータを渡す()
    {
        // バッチ実行
        SampleConsoleOutput.hogeHoge("正しいパラメータ");

        String std = stdout.getOutput();
        String std_err = stdout.getErrorOutput();

        assertThat(std_err.length(), is(0));
        assertThat(std, is("正常終了"));
    }

    /**
     * hogeHogeメソッド異常系のテスト.
     */
    @Test
    public void testHogeHogeパラメータnullを渡す()
    {
        // hogeHoge実行
        SampleConsoleOutput.hogeHoge(null);

        String std = stdout.getOutput();
        String std_err = stdout.getErrorOutput();

        assertThat(std_err, is("エラーが発生"));
        assertThat(std.length(), is(0));
    }
}
7
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
11