Initialization
You can seed a MockFileSystem declaratively (with descriptions), fluently (with a builder), or by copying data in from outside the test.
The first two snippets create:
- a directory
foo/containing a sub-directorybar/and an empty filebar.txt - a file
foo.txtwith content"some file content"
Declarative
var fileSystem = new MockFileSystem();
fileSystem.Initialize().With(
new DirectoryDescription("foo",
new DirectoryDescription("bar"),
new FileDescription("bar.txt")),
new FileDescription("foo.txt", "some file content"));
Fluent
var fileSystem = new MockFileSystem();
fileSystem.Initialize()
.WithSubdirectory("foo").Initialized(d => d
.WithSubdirectory("bar")
.WithFile("bar.txt"))
.WithFile("foo.txt").Which(f => f.HasStringContent("some file content"));
Use HasStringContent(string) or HasBytesContent(byte[]) on the file manipulator to set content.
Initializing inside a specific directory
fileSystem.InitializeIn("current-directory")
.WithASubdirectory()
.WithSubdirectory("foo").Initialized(s => s
.WithAFile())
.WithFile("bar.txt");
This sets current-directory as the working directory and seeds it with:
- a randomly named sub-directory
- a
foo/sub-directory containing one randomly named file - a
bar.txtfile
WithASubdirectory() / WithAFile() use generated names when you don't care about the exact value - useful for tests that operate over whatever they find. WithAFile(string extension) lets you constrain the random name to a specific extension.
InitializeIn(absolutePath) automatically registers the corresponding drive on Windows when the path is rooted.
Bulk subdirectories
fileSystem.Initialize()
.WithSubdirectories("a/b/c", "x/y", "logs");
Creates each path (and any missing parents) in one call.
Accessing what was created
Initialize() returns an IFileSystemInitializer<TFileSystem> exposing:
BaseDirectory- theIDirectoryInfoof the seed rootFileSystem- the underlying file systemthis[int index]- the created entries in the order they were added
var init = fileSystem.Initialize()
.WithFile("foo.txt")
.WithSubdirectory("bar");
var foo = (IFileInfo)init[0];
var bar = (IDirectoryInfo)init[1];
Seeding from a real directory
fileSystem.InitializeFromRealDirectory("test-data");
// or copy the source directory into a different target on the mock:
fileSystem.InitializeFromRealDirectory(@"C:\fixtures\sample-project", "project");
Recursively copies every file and sub-directory from the real path into the mock, preserving creation/last-write/last-access time and attributes. With large fixtures this can be slow - prefer it for small, hand-curated test data.
Seeding from embedded resources
fileSystem.InitializeEmbeddedResourcesFromAssembly(
directoryPath: "fixtures",
assembly: typeof(MyTests).Assembly,
relativePath: "TestData",
searchPattern: "*.json",
searchOption: SearchOption.AllDirectories);
Materializes embedded resources as files inside the mock. Resource names are split on the last . to recover an extension (e.g. MyTests.TestData.users.json becomes fixtures/users.json). relativePath filters which resources are included; searchPattern and searchOption work like Directory.EnumerateFiles.
Real file system: temporary directory with auto-cleanup
For integration tests that hit the real disk, SetCurrentDirectoryToEmptyTemporaryDirectory creates a fresh temp directory, switches Directory.GetCurrentDirectory() to it, and force-deletes everything when the returned IDirectoryCleaner is disposed:
IFileSystem fileSystem = new RealFileSystem();
using IDirectoryCleaner cleaner =
fileSystem.SetCurrentDirectoryToEmptyTemporaryDirectory(prefix: "MyTests-");
// fileSystem.Directory.GetCurrentDirectory() is now an empty temp directory
// On dispose: the directory is force-deleted (read-only flag and all)
The prefix parameter makes leftovers easier to spot in %TEMP% if cleanup ever fails. The optional logger parameter receives diagnostic messages (e.g. retry attempts when antivirus holds a file open).