is it really possible to use classes and interfaces to mock file system without libraries in crystal ?
It is possible to monkey-patch File
and Dir
for your use-case, but if this is for specs then you might find testing with direct IO
inputs would be easier then mocking the file system. For example, take the following method:
def reverse_contents(file : File) : Nil
content = file.gets_to_end.reverse
file.rewind << content
end
This method doesn’t need to have access to a file directly, it can instead use IO
which allows you to do this:
require "spec"
it "reverses contents" do
io = IO::Memory.new
io << "foo bar baz"
io.rewind
reverse_contents io
io.to_s.should eq "zab rab oof"
end
The short answer is yes. Totally possible for you to do something like:
module FileSystemInterface
abstract def write(path : String | Path, content : String) : Nil
abstract def read(path : String | Path) : String
end
class LocalFileSystem
include FileSystemInterface
def write(path : String | Path, content : String) : Nil
File.write path, content
end
def read(path : String | Path) : String
File.read path
end
end
class MockFileSystem
include FileSystemInterface
@files = Hash(String, String).new
def write(path : String | Path, content : String) : Nil
@files[path.to_s] = content
end
def read(path : String | Path) : String
@files[path.to_s]? || raise "File does not exist"
end
end
Then your logic can depend upon FileSystemInterface
, defaulting to LocalFileSystem
, but using MockFileSystem
in specs.
this works with file extensions ? i want to obfuscate the file extension i want to make pdf looks like txt but actually it is txt is it possible with classes and interfaces ?
If that’s what you mean by “filesystem mocking” then I’m not sure I follow why you think you need classes and interfaces. If you just want to save a PDF with a .txt
file extension then you can just do that when you save the file.