Rspec:如何testing文件操作和文件内容

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

File.open "filename", "w" do |file| file.write("text") end 

我想通过rspectesting这个代码。 这样做的最佳做法是什么?

我build议使用这个StringIO ,并确保你的SUT接受一个stream来写入而不是文件名。 这样,可以使用不同的文件或输出(更可重用),包括stringIO(适合testing)

所以在你的testing代码中(假设你的SUT实例是sutObject ,序列化程序名为writeStuffTo

 testIO = StringIO.new sutObject.writeStuffTo testIO testIO.string.should == "Hello, world!" 

stringIO的行为就像一个打开的文件。 所以如果代码已经可以和一个File对象一起工作,那么它将和StringIO一起工作。

对于非常简单的I / O,你可以模拟文件。 所以,给出:

 def foo File.open "filename", "w" do |file| file.write("text") end end 

然后:

 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 

但是,这种方法在存在多个读/写的情况下是平坦的:简单的重构不会改变文件的最终状态,可能导致testing中断。 在这种情况下(可能在任何情况下)你应该更喜欢@Danny Staple的答案。

你可以使用fakefs 。

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

你检查

 File.exists? "filename" 

如果文件被创build。

你也可以直接阅读

 File.open 

并对其内容进行期望。

这是如何模拟文件(与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