我想使用RSpec模拟为块提供固定输入。
红宝石:
class Parser
attr_accessor :extracted
def parse(fname)
File.open(fname).each do |line|
extracted = line if line =~ /^RCS file: (.*),v$/
end
end
end
RSpec的:
describe Parser
before do
@parser = Parser.new
@lines = mock("lines")
@lines.stub!(:each)
File.stub!(:open).and_return(@lines)
end
it "should extract a filename into extracted" do
linetext = [ "RCS file: hello,v\n", "bla bla bla\n" ]
# HELP ME HERE ...
# the :each should be fed with 'linetext'
@lines.should_receive(:each)
@parser.should_receive('extracted=')
@parser.parse("somefile.txt")
end
end
这是一种通过将固定数据传递到其中来测试块内部正常工作的方法。但我无法弄清楚如何使用RSpec模拟机制进行实际喂食。
更新:看起来问题不在于linetext,而在于:
@parser.should_receive('extracted=')
这不是它被调用的方式,在ruby代码中用self.extracted替换它有点帮助,但在某种程度上感觉不对。
答案 0 :(得分:8)
充实'and_yield'的作用:我不认为'and_return'真的是你想要的。这将设置File.open块的返回值,而不是设置为其块的行。要略微更改示例,请说明:
红宝石
def parse(fname)
lines = []
File.open(fname){ |line| lines << line*2 }
end
Rspec的
describe Parser do
it 'should yield each line' do
File.stub(:open).and_yield('first').and_yield('second')
parse('nofile.txt').should eq(['firstfirst','secondsecond'])
end
end
会通过。如果你用'and_return'替换那行
File.stub(:open).and_return(['first','second'])
它将失败,因为正在绕过该块:
expected: ["firstfirst", "secondsecond"]
got: ["first", "second"]
所以底线是使用'and_yield'来模拟'each'类型块的输入。使用'and_return'来模拟这些块的输出。
答案 1 :(得分:4)
我没有配备Ruby&amp; RSpec可用于检查此项,但我怀疑您需要在and_yields
的末尾添加对should_receive(:each)
来电[1]的来电。但是,您可能会发现在这种情况下不使用模拟更简单,例如您可以从StringIO
存根中返回包含linetext
的{{1}}实例。
[1] http://rspec.rubyforge.org/rspec/1.1.11/classes/Spec/Mocks/BaseExpectation.src/M000104.html
答案 2 :(得分:2)
我会想到存根File.open调用
lines = "RCS file: hello,v\n", "bla bla bla\n"
File.stub!(:open).and_return(lines)
这应该足以测试循环内的代码。
答案 3 :(得分:1)
这应该可以解决问题:
describe Parser
before do
@parser = Parser.new
end
it "should extract a filename into extracted" do
linetext = [ "RCS file: hello,v\n", "bla bla bla\n" ]
File.should_receive(:open).with("somefile.txt").and_return(linetext)
@parser.parse("somefile.txt")
@parser.extracted.should == "hello"
end
end
Parser类中有一些错误(它不会通过测试),但这就是我编写测试的方法。