2016-05-19 55 views
2

我是使用RSpec和Ruby進行單元測試的新手,我對如何測試代碼是否使用gets方法,但沒有提示用戶輸入有疑問。使用RSpec測試獲取用戶輸入

這是我試圖測試的代碼。這裏沒什麼瘋狂的,只是一個簡單的班輪。

my_file.rb

My_name = gets 

這裏是我的規格。

require 'stringio' 

def capture_name 
    $stdin.gets.chomp 
end 

describe 'capture_name' do 
    before do 
     $stdin = StringIO.new("John Doe\n") 
    end 

    after do 
     $stdin = STDIN 
    end 

    it "should be 'John Doe'" do 
     expect(capture_name).to be == 'John Doe' 
     require_relative 'my_file.rb' 
    end 
end 

現在這個規範的作品,但是當我運行代碼時,它會提示用戶輸入。我不希望它那樣做。我想簡單地測試get方法是否被調用,並且可能模擬用戶輸入。不確定如何在RSpec中實現這一點。在Python中,我會利用unittest.mock RSpec中是否有類似的方法?

提前致謝!

+0

這是非常類似於你的問題在標準輸出(http://stackoverflow.com/questions/37309874/capturing-stdout-in-rspec) - 我的文件中的代碼在文件加載後立即運行 –

+0

啊。因此,通過在'expect'下面移動'require_relative'my_file.rb'行它確實有效。儘管如此,這仍然不能保證「獲取」方法被調用。如果我將「My_name」的值更改爲除了獲取之外的任何其他值,測試仍然通過。如果'gets'沒有被調用,我需要單元測試失敗。我更新了我的代碼。 – SalceCodec

+0

測試此代碼的正確方法是在需要該文件後對expect(My_name).to eq(「John Doe \ n」)進行測試。然而,由於'require_relative'和標準輸入之間的一些相互作用,測試將失敗。總的來說,在執行類之外的代碼並試圖通過在測試中要求測試代碼時,你會遇到一個不好的途徑。我想建議一條好路徑,但是很難做到這一點。無論如何,將'gets'分配給所需文件中的常量有什麼意義?也許更多的上下文會有幫助 –

回答

2

以下說明如何將gets與您的返回值進行比較。

require 'rspec' 

RSpec.describe do 
    describe 'capture_name' do 
    it 'returns foo as input' do 
     allow($stdin).to receive(:gets).and_return('foo') 
     name = $stdin.gets 

     expect(name).to eq('food') 
    end 
    end 
end 

Failures: 

    1) should eq "food" 
    Failure/Error: expect(name).to eq('food') 

     expected: "food" 
      got: "foo" 

     (compared using ==) 

測試某被調用(如某個功能),可以使用expect($stdin).to receive(:gets).with('foo'),以確保它被調用(一次)用正確的ARGS。此場景中的預期線必須在name = $stdin.gets之前。