在 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
我想为此编写一个不会影响文件系统的规范,以确保它从文件中提取正确的单词,例如:
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
这里的问题是,通过模拟对 的调用File.open
,我还删除了它的返回值,这意味着frobnicate
它将返回nil
。但是,如果我要向链中添加类似File.returns('foo bar baz')
的东西,我最终会得到一个实际上并没有触及我感兴趣的任何代码的测试;块中的内容frobnicate
可以做任何事情并且测试仍然会通过。
我如何frobnicate
在不影响文件系统的情况下适当地测试我的方法?我并不特别依赖任何特定的测试框架,所以如果你的答案是“使用这个可以为你做的很棒的 gem”,那么我可以接受。