Rspec: 没有这样的文件或目录@rb_sysopen -

Rspec: No such file or directory @ rb_sysopen -

我正在尝试为使用 gets 的 ruby 脚本编写一个简单的测试,但我遇到了一些奇怪的行为。

当我 运行 使用 rspec 进行测试时,它可以正常通过,但是一旦我 运行 rspec 使用任何标志,例如 rspec -f jsonrspec -O rand 测试将失败并给我 No such file or directory @ rb_sysopen - -O,其中 -O 是 运行.

的标志

奇怪的是,如果我 运行 rspec 并指定像 rspec spec/gets_spec.rb 这样的测试文件,我会得到一个完全不同的错误:

     Failure/Error: expect { require_relative '../gets' }.to output("Hello, Lena!\n").to_stdout                         
       expected block to output "Hello, Lena!\n" to stdout, but output "Hello, Describe \"gets.rb\" do!\n"
                     Diff:                                                                                                              
@@ -1,2 +1,2 @@                                                                                                         
-Hello, Lena!                                                                                                           
+Hello, Describe "gets.rb" do!                                                                                                                                                                                                                
# ./spec/gets_spec.rb:14:in `block (2 levels) in <top (required)>' 

我无法找出正确的方法来编写我的测试以防止这种情况发生,但我不确定我的代码的哪一部分需要更改。

我正在使用 ruby 2.6.3

我从 this question

了解了测试输入

脚本,gets.rb,看起来像

puts "Hello, #{gets.chomp.capitalize}!"

我的测试看起来像

describe "gets.rb" do
  before do
      $stdin = StringIO.new("lena")
  end

  after do 
      $stdin = STDIN
  end

  it "should output 'Hello, name!'" , points: 1 do
    allow($stdin).to receive(:gets).and_return("lena")

    expect { require_relative "../gets" }.to output("Hello, Lena!\n").to_stdout
  end
end

这是完整的失败消息:

Failures:

  1) gets.rb should output 'Hello, name!'
     Failure/Error: expect { require_relative '../gets' }.to output("Hello, Lena!\n").to_stdout                        
     Errno::ENOENT: 
No such file or directory @ rb_sysopen - -O                                                                          
#./gets.rb:1:in `gets'                     
# ./gets.rb:1:in `gets' 
# ./gets.rb:1:in `<top (required)>' 
# ./spec/gets_spec.rb:14:in `require_relative' 
# ./spec/gets_spec.rb:14:in `block (3 levels) in <top (required)>'
# ./spec/gets_spec.rb:14:in `block (2 levels) in <top (required)>'  

您可以尝试使用一些不同的方法:

describe "gets.rb" do
  it "should output 'Hello, name!'" do
    allow_any_instance_of(Object).to receive(:gets).and_return("lena")

    expect { require_relative "../gets.rb" }.to output("Hello, Lena!\n").to_stdout
  end
end

allow_any_instance_of 我取自 https://makandracards.com/makandra/41096-stubbing-terminal-user-input-in-rspec

Reading user input in console applications is usually done using Kernel#gets.

该页面建议使用 Object.any_instance.stub(gets: 'user input'),但它的语法已经过时,我已经对其进行了更新。