使用RSpec用gets测试用户输入

时间:2016-05-19 16:33:35

标签: ruby unit-testing rspec

我是使用RSpec和Ruby的单元测试的新手,我有一个问题,如何测试我的代码是否使用gets方法,但没有提示用户输入。

这是我要测试的代码。这里没什么了不起的,只是一个简单的单线。

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

现在这个规范有效,但是当我运行代码时,它会提示用户输入。我不希望它那样做。我想简单地测试是否正在调用gets方法并且可能模拟用户输入。不确定如何在RSpec中实现这一点。在Python中我会使用unittest.mock在RSpec中有类似的方法吗?

提前致谢!

1 个答案:

答案 0 :(得分:4)

以下是您如何使用返回值存储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之前。