Just like System.Web.Abstractions, but for System.IO. Yay for testable IO access!
Clone or download
updateaman and fgreinacher Do not delete directories that start with the same path (#433)
Fixes the bug where Directory.Delete was deleting all similarly named directories.

Now it will only delete the directory and subdirectories

Fixes #428
Latest commit a2062c9 Jan 5, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode Add support for running dotnet commands against solution Nov 16, 2018
System.IO.Abstractions.TestingHelpers.Tests Do not delete directories that start with the same path (#433) Jan 5, 2019
System.IO.Abstractions.TestingHelpers Do not delete directories that start with the same path (#433) Jan 5, 2019
System.IO.Abstractions Pass IFileSystem into FileWrapper instead of FileSystem to allow repl… Dec 23, 2018
.editorconfig Add editorconfig Jul 12, 2018
.gitattributes Normalize line endings Apr 25, 2013
.gitignore #351: Add IFileSystem property to base classes (#352) Sep 8, 2018
CONTRIBUTING.md Deploy only from release branch (#410) Dec 4, 2018
Directory.Build.targets Add support for running dotnet commands against solution Nov 16, 2018
LICENSE Add editorconfig Jul 12, 2018
README.md Remove TravisCI badge from README (#416) Dec 2, 2018
StrongName.snk Remove password from strong naming certificate Nov 4, 2017
System.IO.Abstractions.ncrunchsolution Upgrade NCrunch config Mar 16, 2013
System.IO.Abstractions.sln Make package/assembly/directory/project names match (#325) Aug 4, 2018
System.IO.Abstractions.sln.DotSettings Add ReSharper team settings Sep 29, 2014
after.System.IO.Abstractions.sln.targets Add support for running dotnet commands against solution Nov 16, 2018
appveyor.yml Deploy only from release branch (#410) Dec 4, 2018
version.json Bump base version to 3.0 (#408) Dec 7, 2018

README.md

NuGet Build status Dependabot Status


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

NuGet only:

Install-Package System.IO.Abstractions

and/or:

Install-Package System.IO.Abstractions.TestingHelpers

At the core of the library is IFileSystem and FileSystem. Instead of calling methods like File.ReadAllText directly, use IFileSystem.File.ReadAllText. We have exactly the same API, except that ours is injectable and testable.

public class MyComponent
{
    readonly IFileSystem fileSystem;

    // <summary>Create MyComponent with the given fileSystem implementation</summary>
    public MyComponent(IFileSystem fileSystem)
    {
        this.fileSystem = fileSystem;
    }
    /// <summary>Create MyComponent</summary>
    public MyComponent() : this( 
        fileSystem: new FileSystem() //use default implementation which calls System.IO
    ) 
    {
    }

    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.");
        }
    }
}

The library also ships with a series of test helpers to save you from having to mock out every call, for basic scenarios. They are not a complete copy of a real-life file system, but they'll get you most of the way there.

[Test]
public void MyComponent_Validate_ShouldThrowNotSupportedExceptionIfTestingIsNotAwesome()
{
    // Arrange
    var fileSystem = new MockFileSystem(new Dictionary<string, MockFileData>
    {
        { @"c:\myfile.txt", new MockFileData("Testing is meh.") },
        { @"c:\demo\jQuery.js", new MockFileData("some js") },
        { @"c:\demo\image.gif", new MockFileData(new byte[] { 0x12, 0x34, 0x56, 0xd2 }) }
    });
    var component = new MyComponent(fileSystem);

    try
    {
        // Act
        component.Validate();
    }
    catch (NotSupportedException ex)
    {
        // Assert
        Assert.AreEqual("We can't go on together. It's not me, it's you.", ex.Message);
        return;
    }

    Assert.Fail("The expected exception was not thrown.");
}

We even support casting from the .NET Framework's untestable types to our testable wrappers:

FileInfo SomeBadApiMethodThatReturnsFileInfo()
{
    return new FileInfo("a");
}

void MyFancyMethod()
{
    var testableFileInfo = (FileInfoBase)SomeBadApiMethodThatReturnsFileInfo();
    ...
}