Alternative: have an abstract base class that describes a file system API. Have one implementation that builds on top of OS primitives and have another one that is a mock (potentially auto-generated through some mocking framework). That way there is no need to monkey-patch standard library functions at runtime.
I did that within a project of mine, written in Go:
https://github.com/buildbarn/bb-storage/blob/master/pkg/file...
https://github.com/buildbarn/bb-storage/blob/master/pkg/file...
Pretty slick that I can now use https://github.com/golang/mock to automatically generate a mock of that.