{"id":13677493,"url":"https://github.com/TestableIO/System.IO.Abstractions","last_synced_at":"2025-04-29T11:30:59.320Z","repository":{"id":2918582,"uuid":"3928696","full_name":"TestableIO/System.IO.Abstractions","owner":"TestableIO","description":"Just like System.Web.Abstractions, but for System.IO. Yay for testable IO access!","archived":false,"fork":false,"pushed_at":"2025-04-18T21:55:16.000Z","size":4924,"stargazers_count":1563,"open_issues_count":22,"forks_count":261,"subscribers_count":32,"default_branch":"main","last_synced_at":"2025-04-22T17:07:31.791Z","etag":null,"topics":["c-sharp","cross-platform","dotnet","filesystem","io","mocks","tdd","testing"],"latest_commit_sha":null,"homepage":"http://www.nuget.org/packages/System.IO.Abstractions","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TestableIO.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-04-04T13:00:39.000Z","updated_at":"2025-04-18T21:55:18.000Z","dependencies_parsed_at":"2023-10-12T04:59:12.693Z","dependency_job_id":"199b4881-4305-4ba0-b04c-319a7391539b","html_url":"https://github.com/TestableIO/System.IO.Abstractions","commit_stats":{"total_commits":980,"total_committers":157,"mean_commits":6.24203821656051,"dds":0.7275510204081632,"last_synced_commit":"d439c7f61ccca532018d2ed5818a318a2fc69459"},"previous_names":["tathamoddie/system.io.abstractions"],"tags_count":304,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TestableIO%2FSystem.IO.Abstractions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TestableIO%2FSystem.IO.Abstractions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TestableIO%2FSystem.IO.Abstractions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TestableIO%2FSystem.IO.Abstractions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TestableIO","download_url":"https://codeload.github.com/TestableIO/System.IO.Abstractions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250354280,"owners_count":21416748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","cross-platform","dotnet","filesystem","io","mocks","tdd","testing"],"created_at":"2024-08-02T13:00:43.008Z","updated_at":"2025-04-29T11:30:59.314Z","avatar_url":"https://github.com/TestableIO.png","language":"C#","readme":"![System.IO.Abstractions](https://socialify.git.ci/TestableIO/System.IO.Abstractions/image?description=1\u0026font=Source%20Code%20Pro\u0026forks=1\u0026issues=1\u0026pattern=Charlie%20Brown\u0026pulls=1\u0026stargazers=1\u0026theme=Dark)\n[![NuGet](https://img.shields.io/nuget/v/TestableIO.System.IO.Abstractions.svg)](https://www.nuget.org/packages/TestableIO.System.IO.Abstractions)\n[![Build](https://github.com/TestableIO/System.IO.Abstractions/actions/workflows/build.yml/badge.svg)](https://github.com/TestableIO/System.IO.Abstractions/actions/workflows/build.yml)\n[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=TestableIO_System.IO.Abstractions\u0026metric=alert_status)](https://sonarcloud.io/summary/new_code?id=TestableIO_System.IO.Abstractions)\n[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=TestableIO_System.IO.Abstractions\u0026metric=coverage)](https://sonarcloud.io/summary/new_code?id=TestableIO_System.IO.Abstractions)\n[![Renovate enabled](https://img.shields.io/badge/renovate-enabled-brightgreen.svg)](https://renovatebot.com/)\n[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2FTestableIO%2FSystem.IO.Abstractions.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2FTestableIO%2FSystem.IO.Abstractions?ref=badge_shield)\n\nAt 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.\n\n## Usage\n\n```shell\ndotnet add package TestableIO.System.IO.Abstractions.Wrappers\n```\n\n*Note: This NuGet package is also published as `System.IO.Abstractions` but we suggest to use the prefix to make clear that this is not an official .NET package.*\n\n```csharp\npublic class MyComponent\n{\n    readonly IFileSystem fileSystem;\n\n    // \u003csummary\u003eCreate MyComponent with the given fileSystem implementation\u003c/summary\u003e\n    public MyComponent(IFileSystem fileSystem)\n    {\n        this.fileSystem = fileSystem;\n    }\n    /// \u003csummary\u003eCreate MyComponent\u003c/summary\u003e\n    public MyComponent() : this(\n        fileSystem: new FileSystem() //use default implementation which calls System.IO\n    )\n    {\n    }\n\n    public void Validate()\n    {\n        foreach (var textFile in fileSystem.Directory.GetFiles(@\"c:\\\", \"*.txt\", SearchOption.TopDirectoryOnly))\n        {\n            var text = fileSystem.File.ReadAllText(textFile);\n            if (text != \"Testing is awesome.\")\n                throw new NotSupportedException(\"We can't go on together. It's not me, it's you.\");\n        }\n    }\n}\n```\n\n### Test helpers\n\nThe 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.\n\n```shell\ndotnet add package TestableIO.System.IO.Abstractions.TestingHelpers\n```\n\n*Note: This NuGet package is also published as `System.IO.Abstractions.TestingHelpers` but we suggest to use the prefix to make clear that this is not an official .NET package.*\n\n```csharp\n[Test]\npublic void MyComponent_Validate_ShouldThrowNotSupportedExceptionIfTestingIsNotAwesome()\n{\n    // Arrange\n    var fileSystem = new MockFileSystem(new Dictionary\u003cstring, MockFileData\u003e\n    {\n        { @\"c:\\myfile.txt\", new MockFileData(\"Testing is meh.\") },\n        { @\"c:\\demo\\jQuery.js\", new MockFileData(\"some js\") },\n        { @\"c:\\demo\\image.gif\", new MockFileData(new byte[] { 0x12, 0x34, 0x56, 0xd2 }) }\n    });\n    var component = new MyComponent(fileSystem);\n\n    try\n    {\n        // Act\n        component.Validate();\n    }\n    catch (NotSupportedException ex)\n    {\n        // Assert\n        Assert.That(ex.Message, Is.EqualTo(\"We can't go on together. It's not me, it's you.\"));\n        return;\n    }\n\n    Assert.Fail(\"The expected exception was not thrown.\");\n}\n```\n\nWe even support casting from the .NET Framework's untestable types to our testable wrappers:\n\n```csharp\nFileInfo SomeApiMethodThatReturnsFileInfo()\n{\n    return new FileInfo(\"a\");\n}\n\nvoid MyFancyMethod()\n{\n    var testableFileInfo = (FileInfoBase)SomeApiMethodThatReturnsFileInfo();\n    ...\n}\n```\n\n### Mock support\n\nSince version 4.0 the top-level APIs expose interfaces instead of abstract base classes (these still exist, though), allowing you to completely mock the file system. Here's a small example, using [Moq](https://github.com/moq/moq4):\n\n```csharp\n[Test]\npublic void Test1()\n{\n    var watcher = Mock.Of\u003cIFileSystemWatcher\u003e();\n    var file = Mock.Of\u003cIFile\u003e();\n\n    Mock.Get(file).Setup(f =\u003e f.Exists(It.IsAny\u003cstring\u003e())).Returns(true);\n    Mock.Get(file).Setup(f =\u003e f.ReadAllText(It.IsAny\u003cstring\u003e())).Throws\u003cOutOfMemoryException\u003e();\n\n    var unitUnderTest = new SomeClassUsingFileSystemWatcher(watcher, file);\n\n    Assert.Throws\u003cOutOfMemoryException\u003e(() =\u003e {\n        Mock.Get(watcher).Raise(w =\u003e w.Created += null, new System.IO.FileSystemEventArgs(System.IO.WatcherChangeTypes.Created, @\"C:\\Some\\Directory\", \"Some.File\"));\n    });\n\n    Mock.Get(file).Verify(f =\u003e f.Exists(It.IsAny\u003cstring\u003e()), Times.Once);\n\n    Assert.True(unitUnderTest.FileWasCreated);\n}\n\npublic class SomeClassUsingFileSystemWatcher\n{\n    private readonly IFileSystemWatcher _watcher;\n    private readonly IFile _file;\n\n    public bool FileWasCreated { get; private set; }\n\n    public SomeClassUsingFileSystemWatcher(IFileSystemWatcher watcher, IFile file)\n    {\n        this._file = file;\n        this._watcher = watcher;\n        this._watcher.Created += Watcher_Created;\n    }\n\n    private void Watcher_Created(object sender, System.IO.FileSystemEventArgs e)\n    {\n        FileWasCreated = true;\n\n        if(_file.Exists(e.FullPath))\n        {\n            var text = _file.ReadAllText(e.FullPath);\n        }\n    }\n}\n```\n\n## Related projects\n\n-   [`System.IO.Abstractions.Extensions`](https://github.com/TestableIO/System.IO.Abstractions.Extensions)\n  provides convenience functionality on top of the core abstractions.\n\n-   [`System.IO.Abstractions.Analyzers`](https://github.com/TestableIO/System.IO.Abstractions.Analyzers)\n  provides Roslyn analyzers to help use abstractions over static methods. \n\n-   [`Testably.Abstractions`](https://github.com/Testably/Testably.Abstractions)\n  provides alternative test helpers and additional abstractions.\n","funding_links":[],"categories":["C#"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTestableIO%2FSystem.IO.Abstractions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTestableIO%2FSystem.IO.Abstractions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTestableIO%2FSystem.IO.Abstractions/lists"}