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