2010-09-26 52 views
10

我有一個函數,讀取std :: cin的用戶輸入,我想寫一個單元測試插入一些字符串到std :: cin,以便以後從std :: cin提取將讀取該字符串而不是暫停鍵盤輸入。注入字符串'cin'

理想情況下,我會更改函數簽名,以便我可以傳遞一個自定義istream作爲參數,但是我不能這樣做,因爲我有一個固定的接口,我無法更改。我想要什麼,但是它一次只插入一個字符,並且它以相反的順序插入它們(但是我在某處讀取了原本並不是最初的字符可能會有危險,但網站沒有詳細說明原因)。我已經嘗試了幾種方法將字符串注入到cin的內部緩衝區cin.rdbuf()中,但沒有一個可以工作。我也考慮過使用外部測試腳本或創建子進程,但是我想先考慮純C++中的測試。

那麼,有沒有什麼方法將字符串放入cin中?或者你知道一個更好的方法來注入我的「假鍵盤輸入」?

回答

8

如果你真的想使用std :: CIN,試試這個:

int main() { 
    using namespace std; 
    streambuf *backup; 
    istringstream oss("testdata"); 
    backup = cin.rdbuf(); 
    cin.rdbuf(oss.rdbuf()); 
    string str; 
    cin >> str; 
    cout << "read " << str;  
} 

當你從備份做,你可以恢復的std :: CIN的流緩衝。 我並不保證這種可移植性; p

+0

+1。或'stringbuf sb(「testdata」); streambuf * backup = cin.rdbuf(&sb);''。它符合規範,並且是合理的可移植的,但不是很好的做法。哦,是的,一旦輸入用完,他可能必須執行'cin.clear()'來逃避EOF條件:vP。 – Potatoswatter 2010-09-26 10:38:59

+0

+1正是我所要求的(我仍然親自想知道,不管做這樣的事情是個好主意,即使對於白盒測試代碼也是如此)。 – 2010-09-26 11:42:12

13

而不是用cin擰,你可以讓你的程序接受一般std::istream&。正常運行時,只需通過cin即可。在單元測試期間,將它傳遞給您自己創建的I/O流。

+2

這個解決方案真的很棒。如果你想傳遞一個文件作爲你的測試輸入,你可以通過'ifstream'傳遞一個打開的文件,或者如果你想傳遞一個字符串作爲你的測試輸入,你可以簡單地傳遞一個'istringstream'。 – RPGillespie 2017-01-11 22:43:13

0

cin.butback()保證最多隻能處理一個字符,所以你不能放回整個字符串。使用包裝cin的流並允許任意的putback()序列長度。我認爲Boost.Iostream有類似的東西,如果沒有,那麼實現這樣的包裝可能會有所幫助。