Library / SDK
TestableIO/System.IO.Abstractions avatar
TestableIO/System.IO.Abstractions

System.IO.Abstractions for injectable filesystem access in C#

Just like System.Web.Abstractions, but for System.IO. Yay for testable IO access!

1,627 stars260 forksC#MIT

At a glance

What is it?
TestableIO.System.IO.Abstractions replaces direct System.IO calls with injectable filesystem interfaces and test helpers. It suits C# applications that need controlled unit tests, while Testably.Abstractions is the stated focus for new and advanced work.
Who is it for?
Adopt TestableIO.System.IO.Abstractions for an existing C# codebase that already depends on it or needs basic filesystem mocking. Do not choose it for advanced cross-platform simulation, unless compatibility constraints justify the maintenance boundary.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why IFileSystem replaces direct File calls

System.IO.Abstractions addresses a specific testability problem in C# code. Direct calls such as File.ReadAllText and Directory.GetFiles reach the operating system immediately, so a unit test must either touch real files or intercept static methods. The library puts an IFileSystem abstraction in front of those operations. According to the README, production code can use IFileSystem.File.ReadAllText instead of File.ReadAllText while retaining the same API shape. The interface can then receive FileSystem for normal operation or a test implementation such as MockFileSystem.

This is aimed at developers writing components whose behavior depends on files, directories, paths, or filesystem events. It is not a general dependency-injection framework. Its scope is the System.IO surface, with wrappers and interfaces that can be replaced in tests. The package README says that its interfaces expose the top-level APIs, while older abstract base classes still exist for compatibility. That distinction matters for teams deciding how tightly to couple application code to the library's abstractions.

The production and test data flow

The central flow is constructor injection followed by interface calls. A component receives IFileSystem, while FileSystem supplies the default implementation that calls System.IO. A test creates MockFileSystem, places files in an in-memory model, and passes that implementation into the same component. The production method then reads through the injected interface, but the test controls what paths exist and what their contents contain.

The testing example initializes files under c:\ and supplies text, JavaScript, and binary data through MockFileData. When the component enumerates the directory and reads each matching text file, the test can verify both the returned content and the exception path without requiring those files to exist on the test machine. The README also documents casting System.IO.FileInfo to FileInfoBase, which helps code that receives framework file information from an API it does not control.

For event-driven behavior, the library exposes IFileSystemWatcher and IFile interfaces. The Mockolate example configures Exists and ReadAllText, raises a Created event, and verifies calls made by the component. This is useful when a test needs to model a watcher event or force an exception from a read, rather than merely provide a small directory fixture.

Installing wrappers and running a first validation

The README gives the production package installation command. It also states that the package is published as System.IO.Abstractions, but recommends the TestableIO prefix so consumers can tell that it is not an official .NET package. In a .NET project, the package adds the filesystem wrappers used by application code.

shell
dotnet add package TestableIO.System.IO.Abstractions.Wrappers

After installation, inject IFileSystem into the component. The default constructor uses FileSystem, which delegates to System.IO. The example below is the README's component pattern, with the method body shortened to the essential filesystem interaction.

csharp
public class MyComponent
{
    readonly IFileSystem fileSystem;

    public MyComponent(IFileSystem fileSystem)
    {
        this.fileSystem = fileSystem;
    }

    public void Validate()
    {
        foreach (var textFile in fileSystem.Directory.GetFiles(
            @"c:\", "*.txt", SearchOption.TopDirectoryOnly))
        {
            var text = fileSystem.File.ReadAllText(textFile);
            if (text != "Testing is awesome.")
                throw new NotSupportedException("We can't go on together. It's not me, it's you.");
        }
    }
}

For a test project, install the testing helpers separately. The package name is explicitly documented as TestableIO.System.IO.Abstractions.TestingHelpers.

shell
dotnet add package TestableIO.System.IO.Abstractions.TestingHelpers

MockFileSystem and event assertions

MockFileSystem is intended for basic filesystem scenarios, not for reproducing every operating-system detail. A test can create files with MockFileData and pass the resulting object directly to the production component. The test in the README places three files into a dictionary, including a binary file represented by a byte array. It then asserts that Validate throws NotSupportedException when the text does not match the expected value.

This approach gives the test control over file content and path layout. It also makes the expected result explicit without creating files in the current directory or depending on a host-specific c:\ path. The limitation is equally explicit: the README says the helpers are not a complete copy of a real-life filesystem. A unit test that depends on permissions, unusual device behavior, operating-system-specific path semantics, or real file locking should not assume that MockFileSystem reproduces those conditions.

Watcher testing uses interfaces rather than only an in-memory directory. The documented Mockolate example creates IFileSystemWatcher and IFile mocks, configures Exists to return true, configures ReadAllText to throw OutOfMemoryException, raises the Created event, and verifies that Exists was invoked once. This supports precise unit tests for event handlers, but it also shifts responsibility to the test author for matching event arguments and call behavior.

Compatibility limits and the Testably.Abstractions boundary

The project is not positioned as the primary home for new filesystem abstraction features. The README says that Testably.Abstractions uses the same interfaces, so switching between the testing libraries does not require production code changes. It also says that both projects share the same maintainer, while active development and new features are primarily focused on Testably.Abstractions.

That creates a clear selection rule. Use TestableIO.System.IO.Abstractions when the codebase needs basic mocking, direct manipulation of MockFileData or MockDirectoryData, or already has TestableIO integration. The README points to Testably.Abstractions for advanced FileSystemWatcher scenarios, SafeFileHandles, multiple drives, ITimeSystem and IRandomSystem, and cross-platform simulation across Linux, macOS, and Windows. The shared interface surface reduces migration friction, but it does not mean the two packages have identical simulation behavior or feature scope.

The last push was on 2026-10-16, and the repository is not archived. Recent releases include v22.3.0 on 2026-09-28, v22.2.0 on 2026-07-12, and v22.1.1 on 2026-04-09. The project should therefore be described as receiving recent maintenance, while its own documentation says continued work is mainly for stability and compatibility and that significant new functionality is unlikely.

License and upgrade considerations

The repository identifies the project as licensed under MIT. That permits use, modification, distribution, and inclusion in larger works under the license terms, subject to its notice and conditions. This paragraph is a technical summary of the declared license, not legal advice. Teams should retain the required license notice and review their own compliance obligations.

For upgrades, the package name includes the TestableIO prefix even though the README says the package is also published as System.IO.Abstractions. That distinction can affect package references, namespace expectations, and dependency resolution, so an upgrade should check which package identity the solution actually uses. The documented release cadence shows recent versioned packages, but the README does not provide a compatibility matrix or a rollback procedure. It also does not claim that every MockFileSystem behavior matches a physical filesystem. Those are points to verify against the target .NET version and the tests that depend on filesystem semantics before upgrading.

Editorial conclusion

Adopt TestableIO.System.IO.Abstractions for an existing C# codebase that already depends on it or needs basic filesystem mocking. Do not choose it for advanced cross-platform simulation, unless compatibility constraints justify the maintenance boundary. Verify the target framework, package compatibility, and whether Testably.Abstractions now fits the project before adding new abstractions.

Frequently asked questions

How do I install System.IO.Abstractions?

The README recommends `dotnet add package TestableIO.System.IO.Abstractions.Wrappers`. For tests, it documents `dotnet add package TestableIO.System.IO.Abstractions.TestingHelpers`.

What is the difference between FileSystem and MockFileSystem?

FileSystem is the default implementation that calls System.IO. MockFileSystem is a test helper that stores in-memory files and directories, but the README explicitly says it is not a complete copy of a real-life filesystem.

Should I choose TestableIO.System.IO.Abstractions or Testably.Abstractions?

The README recommends TestableIO.System.IO.Abstractions for basic mocking, direct MockFileData and MockDirectoryData manipulation, and existing integrations. It points to Testably.Abstractions for advanced watchers, SafeFileHandles, multiple drives, extra abstractions, and cross-platform simulation.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. TestableIO/System.IO.Abstractions on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/testableio-system-io-abstractions.svg)](https://hysenlabs.com/projects/testableio-system-io-abstractions)