Test with an isolated filesystem
Provide MemoryFileSystem.layer to code under test when each test should use disposable filesystem state without
reading or writing the host disk.
Keep the program independent of storage
Write production code against Effect's FileSystem.FileSystem service:
import { Effect, FileSystem } from "effect"
const writeManifest = (version: string) =>
Effect.gen(function*() {
const fs = yield* FileSystem.FileSystem
yield* fs.makeDirectory("/dist", { recursive: true })
yield* fs.writeFileString(
"/dist/manifest.json",
JSON.stringify({ version })
)
return yield* fs.readFileString("/dist/manifest.json")
})The program does not know whether its files are stored in memory or on the host.
Provide fresh state for each test
Run each test program with the memory layer:
import { MemoryFileSystem } from "@effect-vfs/memory"
import { Effect } from "effect"
const first = await Effect.runPromise(
writeManifest("first").pipe(Effect.provide(MemoryFileSystem.layer))
)
const second = await Effect.runPromise(
writeManifest("second").pipe(Effect.provide(MemoryFileSystem.layer))
)
console.log({ first, second })Each top-level execution materializes independent storage. One run cannot observe files created by the other.
Your test runner can place the Effect.runPromise call inside its normal test function and assert on the returned
value. Keep the assertion library outside the Effect program so the example remains portable between runners.
Understand layer sharing
Effect memoizes a layer within one layer graph. When several services in the same graph receive the same
MemoryFileSystem.layer, they share one filesystem service and one volume.
That sharing is useful when collaborators should see the same files. Wrap the layer with Layer.fresh when separate
parts of one graph must materialize independent filesystems.
import { Layer } from "effect"
const isolatedFileSystem = Layer.fresh(MemoryFileSystem.layer)Separate calls to MemoryFileSystem.make also create independent services directly. Use
MemoryFileSystem.bind instead when multiple adapters should deliberately share
an existing core volume.
Keep host access outside the assumption
The memory adapter replaces Effect's FileSystem service. It cannot intercept code that directly uses:
node:fs;- child processes;
- native extensions; or
- another API that accesses the host filesystem independently.
A test is isolated only when the code under test obtains filesystem access through the provided Effect service.
Handle scoped resources
Open files, temporary resources, and watch subscriptions are scoped. Keep the owning Effect.scoped workflow alive
while those resources are in use. Closing the scope releases its handles and subscriptions.
For the adapter constructors and layer types, see the
MemoryFileSystem API reference.