Skip to content

hitch17/hitchfs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

62 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The purpose of HitchFS is to provide an easy way to test file system 
operations in Java (particularly those in java.io.File) as safely as possible.

The primary benefits are:

  - Dangerous file operations, such as delete, are limited to the behavior
    that you define in your tests.  This helps prevent bugs from performing 
    accidental damage, and is especially useful when working with someone else's
    code or library.
    
    // Example
    StubFileSystem fs = new StubFileSystem() {
      @Override
      public boolean delete(FakeFile fake) {
        throw new RuntimeException("deleting me is really bad!");
      }
    };
    FakeFile fake = fs.file("something-critical.txt");
    fake.delete(); // causes the RuntimeException to be thrown.  
  
  - I/O operations are costly, and wasteful in tests. The should be avoided as 
    much as possible, but at the same time, reading/writing files is likely one 
    of the most critical operations for your application to do correctly, and requires
    significant testing.  HitchFS allows you to test while redirecting to in-memory
    objects such as ByteArrayInputStream or writing to a MessageDigestOutputStream and
    just verifying an md5 sum in your test:  

    // Writing Example
    String message = "fake file with text.";
    ByteArrayOutputStream out = new ByteArrayOutputStream(message.length());
    final MessageDigestOutputStream md5 = md5().setOutput(out);
    StubFileSystem fs = new StubFileSystem() {
      @Override
      public OutputStream getOutputStream(FakeFile fake, boolean append) throws IOException {
        return md5;
      }
    };
    FakeFile file = fs.file("fakedir/fakefile2.txt");
    Writer writer = fs.writer(file);
    writer.write(message);
    writer.close();
    assertEquals("9d2110c9a94894f10cfee35afaf8ceb2", md5.getDigestAsHex());
    assertEquals(message, new String(out.toByteArray()));
    
    // Reading Example
    String expected = "this is some text in memory.";
    StubFileSystem fs = new StubFileSystem() {
      @Override
      public InputStream getInputStream(FakeFile fake) throws IOException {
        StringProp p = fake.getProperty(StringProp.class);
        if (p == null) {
          throw new FileNotFoundException();
        }
        return new ByteArrayInputStream(p.data.getBytes());
      }
    };
    FakeFile file = fs.file("fakedir/doesntexist.txt")
      .withProperty(new StringProp(expected));
    Reader reader = fs.reader(file);
    char[] chars = new char[expected.length() + 5];
    int len = reader.read(chars);
    reader.close();
    assertEquals(expected, new String(chars, 0, len));

    // Reading Example
    String expected = "this is some text in memory.";
    StubFileSystem fs = new StubFileSystem() {
      @Override
      public InputStream getInputStream(FakeFile fake) throws IOException {
        StringProp p = fake.getProperty(StringProp.class);
        if (p == null) {
          throw new FileNotFoundException();
        }
        return new ByteArrayInputStream(p.data.getBytes());
      }
    };
    FakeFile file = fs.file("fakedir/doesntexist.txt")
      .withProperty(new StringProp(expected));
    Reader reader = fs.reader(file);
    char[] chars = new char[expected.length() + 5];
    int len = reader.read(chars);
    reader.close();
    assertEquals(expected, new String(chars, 0, len));

and StringProp is just:

  class StringProp implements FileProp {
    private final String data;
    public StringProp(String data) {
      this.data = data;
    }
  }


Then, when you're in your real application, just use DefaultFileSystem to get
the real Java implementations of File, File Streams, and File Reader/Writers.
    

About

A facility for safely testing filesystem operations in Java

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages