我想使用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=')
这不是它的调用方式,用红色代码替换它,self.extracted =有点帮助,但不知何故感觉不对.
要充实"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'来模拟这些块的输出.