In my app, I have the following code:
File.open "filename", "w" do |file| file.write("text") end
I want to test this code via RSpec. What are the best practices for doing this?
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.new sutObject.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") end end
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 end end
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With