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

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

``` 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));
	}
}
```