2009年11月10日 星期二

Unit Test 使用 System.in 輸入的物件

有時我們會有程式是需要從 System.in 輸入資料來進行運算的,我們會這樣寫:
BufferedReader inputBr = new BufferedReader(new InputStreamReader(System.in));
String input = inputBr.readLine();
但在寫UnitTest時,不可能測試到一半還要去輸入一些資訊到 console,有違自動化的架構。
且在 ant 結合 junit 時,遇到這種狀況會直接測試失敗,這時我們可以透過 mock System.in 的方式,
完成這一個測試,首先待測物件不可以直接使用 System.in 而是在建構子上加上一個,
傳入 InputStream的建構子,而預設建構子則以 System.in 當作該 InputStream,如:

public LcanorusMain() {
this(System.in);
}
public LcanorusMain(InputStream in) {
this.systemIn = in;
}

真正執行時是使用預設建構子,而測試時就是使用有 InputStream 參數的建構子,
並且傳入假造的 mock InputStream 即可:

@Before
public void before() {
lcMain = new LcanorusMain(new SystemInMockInputStream());
}

假造的 mock InputStream 實作重點就是將所要回傳的資料轉成 byte 再一一由read()方法傳回。
且完成所有 byte 後要傳回 -1 表示結束。

private class SystemInMockInputStream extends InputStream {
private byte[] cmdBytes = "fexit\n".getBytes();
private int readIndex = 0;

@Override
public int read() throws IOException {
if (readIndex < cmdBytes.length) {
int ret = cmdBytes[readIndex];
readIndex++;
return ret;
} else {
return -1;
}
}
}

沒有留言:

張貼留言