Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 如何恰当地模拟一个返回yield的方法?_Ruby_Unit Testing_Rspec_Ruby Mocha - Fatal编程技术网

Ruby 如何恰当地模拟一个返回yield的方法?

Ruby 如何恰当地模拟一个返回yield的方法?,ruby,unit-testing,rspec,ruby-mocha,Ruby,Unit Testing,Rspec,Ruby Mocha,在Ruby中,采用块的方法很常见,如下所示: class File def open(path, mode) perform_some_setup yield ensure do_some_teardown end end def frobnicate File.open('/path/to/something', 'r') do |f| f.grep(/foo/).first end end 方法的外观也是非常惯用的: class Fil

在Ruby中,采用块的方法很常见,如下所示:

class File
  def open(path, mode)
    perform_some_setup
    yield
  ensure
    do_some_teardown
  end
end
def frobnicate
  File.open('/path/to/something', 'r') do |f|
    f.grep(/foo/).first
  end
end
方法的外观也是非常惯用的:

class File
  def open(path, mode)
    perform_some_setup
    yield
  ensure
    do_some_teardown
  end
end
def frobnicate
  File.open('/path/to/something', 'r') do |f|
    f.grep(/foo/).first
  end
end
我想为此编写一个不影响文件系统的规范,确保它从文件中提取正确的单词,比如:

describe 'frobnicate' do
  it 'returns the first line containing the substring foo' do
    File.expects(:open).yields(StringIO.new(<<EOF))
      not this line
      foo bar baz
      not this line either
    EOF
    expect(frobnicate).to match(/foo bar baz/)  
  end
end
描述“Frobnite”的用法
它“返回包含子字符串foo”do的第一行

File.expects(:open).yields(StringIO.new(似乎您只需要稍微不同地模拟对
File
的调用。我在原样运行您的代码时遇到语法错误,因此我不确定您使用的是哪个版本的RSpec,但如果您使用的是3.x,这将完成以下工作:

Frobnite_spec.rb
gem'rspec',“~>3.4.0”
需要“rspec/自动运行”
RSpec.configure do | config|
config.mock_with:rspec
结束
def泡沫酸盐
打开('/path/to/something',r')do | f|
f、 grep(/foo/)。首先
结束
结束
RSpec.description“frobnite”do
它“返回包含子字符串foo”do的第一行
允许(文件)。接收(:打开)。并调用原始

允许(文件).to receive(:open).and_yield StringIO.new使用minitest可以像我下面发布的那样完成。我添加了整个可运行文件,因此您可以使用ruby-Ilib:test test_File.rb从命令行对其进行测试:

def frobnicate
  found_string = nil
  File.open('/path/to/something', 'r') do |f|
    found_string = f.grep(/foo/).first
  end
  found_string
end

class FrabnicateTest < Minitest::Test
  def test_it_works
    mock_file = StringIO.new(%(
      not this line
      foo bar baz
      not hthis line either
    ))
    search_result = nil
    File.stub(:open, nil, mock_file) do
      search_result = frobnicate
    end
    assert_match(/foo bar baz/, search_result)
  end
end
def泡沫酸盐
找到字符串=零
打开('/path/to/something',r')do | f|
找到\u string=f.grep(/foo/)。第一个
结束
找到你的字符串
结束
类FrabnicateTest<最小测试::测试
def测试功能正常
mock_file=StringIO.new(%)(
不是这条线
福吧巴兹酒店
这条线也不行
))
搜索结果=nil
存根(:open,nil,mock_File)do
搜索结果=Frobnite
结束
断言匹配(/foo-bar-baz/,搜索结果)
结束
结束

啊,对于语法错误,我很抱歉;为了得到一个MWE,我削减了很多原始代码。看起来你的解决方案是通过rspec mock实现的,而我写的是通过Mocha实现的。不幸的是,当我使用你的解决方案时,我得到了一个
未定义的方法allow
;我使用的是rspec 3.4.1。你使用的是什么Ruby版本?忽略-我更新了test设置,以避免与Mocha的冲突。刚刚用rubies 1.9.3、2.0.0和2.1.2进行了尝试,我可以肯定问题出在config.mock_上。一旦设置到位,我可以模拟调用以打开该特定文件并完全实现我想要的。感谢您的帮助!我真正想要避免的是编辑
frobnite
的定义只是为了让一些测试能够针对它运行。测试服务于代码,而不是相反。测试的困难在于有一种气味告诉我们应该在测试的代码上做得更好。TDD对我来说的一个卖点是测试鼓励我们编写更好的代码。你的代码在我看来会更好f它没有对文件类的依赖项进行硬编码。你可以比我更信任minitest的创建者:在internet上搜索有关硬编码依赖项的信息。这样代码就可以轻松地使用(也可以进行测试)。