2016-05-19 16 views
2

RSpecとRubyを使用したユニットテストの初心者です。私のコードがgetsメソッドを使用しているかどうかをテストする方法はありますが、ユーザーの入力は求めません。RSpecを使用してユーザー入力をテストする

ここに私がテストしようとしているコードがあります。何もここに狂っていない、ちょうど単純な1つのライナー。

My_name = gets 

my_file.rbは、ここに私の仕様です。

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 

この仕様は機能しますが、コードを実行すると、ユーザー入力が求められます。私はそれをしたくありません。 getsメソッドが呼び出されているかどうかを単純にテストして、おそらくユーザー入力を模擬したいと考えています。これをRSpecでどのように達成するかはわかりません。 Pythonでは、私はunittest.mockをRSpecに似たメソッドを利用していますか?

ありがとうございます!

+0

これはstdout(http://stackoverflow.com/questions/37309874/capturing-stdout-in-rspec)に関するご質問と非常によく似ています。ファイルがロードされるとすぐにファイル内のコードが実行されます。 –

+0

Ah 。ですから 'expect_'の下の' require_relative 'my_file.rb''行を動かすことで動作しました。どのようにして、これはまだ、「取得する」メソッドが呼び出されていることを保証しません。私が 'My_name'の値をgets以外のものに変更した場合、テストは引き続き行われます。 '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 ==) 

あなたはそれが正しい引数で(1回)と呼ばれていることを確認するためにexpect($stdin).to receive(:gets).with('foo')を使用することができます。このシナリオの期待値ラインは、name = $stdin.getsの前になければなりません。

関連する問題