RSpec: how to test file operations and file content RSpec: how to test file operations and file content ruby ruby

RSpec: how to test file operations and file content


I would suggest using StringIO for this and making sure your SUT accepts a stream to write to instead of a filename. That way, different files or outputs can be used (more reusable), including the string IO (good for testing)

So in your test code (assuming your SUT instance is sutObject and the serializer is named writeStuffTo:

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

String IO behaves like an open file. So if the code already can work with a File object, it will work with StringIO.


For very simple i/o, you can just mock File. So, given:

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

then:

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  endend

However, this approach falls flat in the presence of multiple reads/writes: simple refactorings which do not change the final state of the file can cause the test to break. In that case (and possibly in any case) you should prefer @Danny Staple's answer.


This is how to mock File (with rspec 3.4), so you could write to a buffer and check its content later:

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