How do you stub a file.read that happens inside a File.open block?

I should note that File.open is just one part of Ruby’s very large I/O API, and so your test is likely to be very strongly coupled to your implementation, and unlikely to survive much refactoring. Further, one must be careful with “global” mocking (i.e. of a constant or all instances) as it can unintentionally mock usages elsewhere, causing confusing errors and failures.

Instead of mocking, consider either creating an actual file on disk (using Tempfile) or using a broader I/O mocking library (e.g. FakeFS).

If you still wish to use mocking you can somewhat safely stub File.open to yield a double (and only when called with the correct argument):

file = instance_double(File, read: 'stubbed read')
allow(File).to receive(:open).and_call_original
allow(File).to receive(:open).with('file.txt') { |&block| block.call(file) }

or, somewhat dangerously, stub all instances:

allow_any_instance_of(File).to receive(:read).and_return('stubbed read')

Tags:

Ruby

Rspec