canni
canni

Reputation: 5885

How to mock/abstract filesystem in go?

I would like to be able to log every write/read that my go app issues to the underlying OS, and also (if it's possible) completely replace FS with one that resides only in memory.

Is it possible? How? Maybe there is a ready-to-Go solution?

Upvotes: 48

Views: 47200

Answers (4)

Zombo
Zombo

Reputation: 1

You can use the testing/fstest package:

package main
import "testing/fstest"

func main() {
   fs := fstest.MapFS{
      "hello.txt": {
         Data: []byte("hello, world"),
      },
   }
   data, err := fs.ReadFile("hello.txt")
   if err != nil {
      panic(err)
   }
   println(string(data) == "hello, world")
}

https://godocs.io/testing/fstest

Upvotes: 23

Ryan Walls
Ryan Walls

Reputation: 7092

For those looking to solve the problem of mocking out your filesystem during testing, checkout @spf13's Afero library, https://github.com/spf13/afero. It does everything that the accepted answer does, but with better documentation and examples.

Upvotes: 34

FrontierPsycho
FrontierPsycho

Reputation: 743

Just because this question pops up pretty high when googling for this matter:

I don't know about logging reads and writes, but for a filesystem residing only in memory, I've found blang/vfs. I haven't used in production, and it says it's alpha and interfaces are likely to change. Use it at your own risk.

I suppose you could implement it to log reads and writes.

Upvotes: 1

Fred Foo
Fred Foo

Reputation: 363607

This is straight from Andrew Gerrand's 10 things you (probably) don't know about Go:

var fs fileSystem = osFS{}

type fileSystem interface {
    Open(name string) (file, error)
    Stat(name string) (os.FileInfo, error)
}

type file interface {
    io.Closer
    io.Reader
    io.ReaderAt
    io.Seeker
    Stat() (os.FileInfo, error)
}

// osFS implements fileSystem using the local disk.
type osFS struct{}

func (osFS) Open(name string) (file, error)        { return os.Open(name) }
func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) }

For this to work, you will need to write your code to take a fileSystem argument (maybe embed it in some other type, or let nil denote the default filesystem).

Upvotes: 48

Related Questions