Rspec:如何测试文件操作和文件内容

pet*_*hka 42 ruby testing file-io rspec file

在我的应用程序中我有这样的代码:

File.open "filename", "w" do |file|
  file.write("text")
end
Run Code Online (Sandbox Code Playgroud)

我想通过rspec测试这段代码.这样做的最佳做法是什么?

Dan*_*ple 57

我建议使用StringIO此方法并确保您的SUT接受要写入的流而不是文件名.这样,可以使用不同的文件或输出(更可重用),包括字符串IO(适用于测试)

所以在你的测试代码中(假设你的SUT实例是sutObject,并且序列化器被命名为writeStuffTo:

testIO = StringIO.new
sutObject.writeStuffTo testIO 
testIO.string.should == "Hello, world!"
Run Code Online (Sandbox Code Playgroud)

字符串IO的行为类似于打开的文件.因此,如果代码已经可以使用File对象,它将与StringIO一起使用.

  • 很好的答案,我知道它没有被问到,但如果它也包括合作伙伴“阅读”示例,那就太完美了。 (2认同)

Way*_*rad 47

对于非常简单的i/o,您可以只模拟File.所以,给定:

def foo
  File.open "filename", "w" do |file|
    file.write("text")
  end
end
Run Code Online (Sandbox Code Playgroud)

然后:

describe "foo" do

  it "should create 'filename' and put 'text' in it" do
    file = mock('file')
    File.should_receive(:open).with("filename", "w").and_yield(file)
    file.should_receive(:write).with("text")
    foo
  end

end
Run Code Online (Sandbox Code Playgroud)

但是,这种方法在存在多次读/写时会失败:简单的重构不会改变文件的最终状态,这会导致测试中断.在那种情况下(可能在任何情况下)你应该更喜欢@Danny Staple的回答.


小智 18

你可以使用fakefs.

它存根文件系统并在内存中创建文件

你检查一下

File.exists? "filename" 
Run Code Online (Sandbox Code Playgroud)

如果文件已创建.

您也可以阅读它

File.open 
Run Code Online (Sandbox Code Playgroud)

并对其内容运行期望.


Edu*_*ana 18

这是如何模拟文件(使用rspec 3.4),因此您可以写入缓冲区并稍后检查其内容:

it 'How to mock File.open for write with rspec 3.4' do
  @buffer = StringIO.new()
  @filename = "somefile.txt"
  @content = "the content fo the file"
  allow(File).to receive(:open).with(@filename,'w').and_yield( @buffer )

  # call the function that writes to the file
  File.open(@filename, 'w') {|f| f.write(@content)}

  # reading the buffer and checking its content.
  expect(@buffer.string).to eq(@content)
end
Run Code Online (Sandbox Code Playgroud)